5
\$\begingroup\$

I have this code that places a marker and on mouse-over this marker is scaled out and then back to the 'original' scale:

this.drawPerson = function () {
 self.svg.append("path")
 .attr("d", personPath)
 .attr("transform", "translate(100,100)scale(0.1)")
 .attr("class", "member")
 .style("fill", "steelblue")
 .on("mouseover", function(){
 d3.select(this).transition()
 .style("fill", "red")
 .attr("transform", "translate(100,100)scale(0.2)")
 })
 .on("mouseout", function() {
 d3.select(this).transition()
 .style("fill", "steelblue")
 .attr("transform", "translate(100,100)scale(0.1)")
 });
}

The x and y are the coordinates for the position on the canvas.

Here is the example: http://jsfiddle.net/SuTZR/8/

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 23, 2012 at 11:42
\$\endgroup\$
6
  • 1
    \$\begingroup\$ What's wrong with it as it stands? Performance? \$\endgroup\$ Commented Jul 24, 2012 at 8:40
  • \$\begingroup\$ i was thinking that the mouse out could just be reset as the original, rather then having to set it again. similar to the way is done with css \$\endgroup\$ Commented Jul 24, 2012 at 9:28
  • \$\begingroup\$ Like when you mouseout of an element with css hover set to something different? I think I see what you mean, but you are doing an animated transform, which is a lot more complex than simply switching from state to state. You could use CSS hover for this if the browser supported a transform like that natively, but until CSS3 is widely adopted, it's not going to be possible. Examples here: tympanus.net/codrops/2011/11/07/animated-buttons-with-css3 \$\endgroup\$ Commented Jul 24, 2012 at 10:05
  • \$\begingroup\$ As usual, IE spoils it for the rest of us: w3schools.com/cssref/css3_browsersupport.asp \$\endgroup\$ Commented Jul 24, 2012 at 10:07
  • \$\begingroup\$ @MattGibson Since IE<9 doesn't support SVG at all, I don't think that is a problem. \$\endgroup\$ Commented Jul 25, 2012 at 9:17

2 Answers 2

2
\$\begingroup\$

There does not seem to be a great way of solving this.

The best I can propose is to capture the style that you will re-set to into a function and use that function both during initialization and mouseout, this makes the code DRY'er, but not necessarily nicer:

this.drawPerson = function () {
 function style( svg ){
 return svg.style("fill", "steelblue") 
 .attr("transform", "translate(100,100)scale(0.1)");
 }
 style( self.svg.append("path")
 .attr("d", personPath)
 .attr("class", "member") )
 .on("mouseover", function(){
 d3.select(this).transition()
 .style("fill", "red")
 .attr("transform", "translate(100,100)scale(0.2)")
 })
 .on("mouseout", function() {
 style( d3.select(this).transition() )
 });
}
answered Dec 30, 2013 at 15:20
\$\endgroup\$
1
\$\begingroup\$

Okay so this answer does not try to change your code by functionalizing anything or what have you ... but it does optimize it:

function MyClient() {
 var self = this,
 personPath = "m 1.4194515,-160.64247 c 33.5874165,0 60.8159465,-25.97005 60.8159465,-58.00952 0,-32.0404 -27.22755,-58.0114 -60.8159465,-58.0114 -33.5883965,0 -60.8159415,25.971 -60.8159415,58.0114 0,32.0404 27.228527,58.00952 60.8159415,58.00952 z m 81.9575765,26.25762 C 70.531608,-146.64352 55.269688,-153.983 0.08110256,-153.983 c -55.19742156,0 -70.08915856,7.96609 -82.28062656,19.59815 -12.197359,11.62926 -8.081167,135.7024419 -8.081167,135.7024419 L -63.292733,-59.848397 -46.325227,122.37766 2.6291765,29.116913 48.308878,122.37766 64.467298,-59.848397 91.457218,1.3175919 c 0,-8e-4 4.76917,-123.4484419 -8.08019,-135.7024419 z",
 fullCanvas = "100%",
 w = $('#canvas').width(),
 mapCanvasHeight = (w * 0.75),
 transformVal = "translate(100,100)scale(0.";
 this.init = function() {
 self.drawCanvas();
 self.drawRect();
 self.drawPerson();
 }
 this.drawCanvas = function () {
 self.svg = d3.select('#canvas')
 .append('svg:svg')
 .attr({
 width:fullCanvas,
 height:fullCanvas,
 viewBox:("0 0 " + w + " " + mapCanvasHeight)
 });
 }
 this.drawRect = function () {
 self.svg
 .append("rect")
 .attr({
 x:0,
 y:0,
 width:w,
 height:mapCanvasHeight,
 fill:"black"
 });
 }
 this.drawPerson = function () {
 self.svg
 .append("path")
 .attr({
 d:personPath,
 transform:transformVal+"1)",
 class:"member",
 fill:"steelblue"
 })
 .on({
 mouseenter:function(){
 d3.select(this).transition()
 .style({
 fill:"red"
 })
 .attr({
 transform:transformVal+"2)"
 });
 },
 mouseleave:function() {
 d3.select(this).transition()
 .style({
 fill:"steelblue",
 })
 .attr({
 transform:transformVal+"1)"
 });
 }
 }); 
 }
 this.init();
};
var MyClient;
jQuery(function() {
 MyClient = new MyClient();
});

The key here is the DOM object use of your methods:

  • style
  • attr
  • on

This will be faster for three reasons, one major and two minor:

  • Major = by consolidating your assignments of attributes and mouseenter / mouseleave into a single bind you are applying to the object once instead of many times consecutively, and as we all know the most expensive action in jQuery is DOM querying
  • Minor = changing mouseover and mouseout to mouseenter and mouseleave respectively prevents excessive firing (mouseover will fire everytime you move the mouse and it is over the object)
  • Minor = use of the DOM object rather than string means less parsing and conversion efforts for the JS compiler to perform

Here is a working jsFiddle.

I also did a couple of minor tweaks like consolidate the variables at the top, assign the "100%" value to a variable, rename your width variable (width is a native DOM property for all elements, bad idea to use it as a variable name), and set your transform value to a variable except for the 1 or 2 at the end, but these are more coding style than optimizations.

answered Jan 1, 2014 at 16:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.