elias elias - 3 months ago 18
Javascript Question

Transition destroys SVG rotation

I am working on a JavaScript project, and as part of it, trying to rotate an svg path element around a given point.
Here is a simplified example of the js file:

var angle=0;
d3.select("#canvas")
.append("path")
.attr("id", "sector")
.attr("fill", "red")
.attr("d", "M150,150 L150,50 A100,100 0 0,1 236.6,200 Z")
.on("click", function(){
console.log("click");
angle=(angle+120)%360;
d3.select("#sector")
.transition().duration(2500) //removing this line leads to a nice transform attribute in the resulting html
.attr("transform","rotate("+angle+",150,150)");
})


And the html is just:

<svg id="canvas" width="300" height="300">
<circle cx="150" cy="150" r="100" stroke="blue" fill="none"/>
</svg>


Here you can find it on JSfiddle.

As the comment in the above excerpt suggests, it all works fine with the 3-argument version of the rotate function, where I can specify the x and y coordinates of the point which I want to use as the center of rotation. The resulting path element gets a transform attribute with the value of
"rotate(120,150,150)"
Unless I want to use a transition.

When I insert the line about the transition, the transformation gets some weird extra things added, it looks like
"translate(354.9038105676658, 95.09618943233417) rotate(119.99999999999999) skewX(-3.1805546814635176e-15) scale(0.9999999999999999,0.9999999999999999)"


I guess in the background the non-(0,0)-centered rotation gets replaced with some translations and a (0,0)-centered rotation, just as you can do it in geometry. The position and orientation after the transition is fine indeed. However, during the transformation the element is moving on a funny path, in the example the sector leaves the circle.

Is there a way I can suppress the transition doing all these transformations and just apply a single non-(0,0)-based rotation?

Are there any other workarounds?

Changing the transform-origin for the path element attribute did not seem to work, but maybe I was doing it wrong.

I am looking for a CSS-free solution. It is an architectural decision which I cannot overrule in the project.

As you see, D3 is already involved in the project, but I would like to use as few additional external libraries as possible.

Thanks in advance!

Answer

create your arc with its center at (0,0). Then translate it to the center of the circle. Then the d3 transition will work nicely as follows:

 d3.select("#sector")
  .transition().duration(2500)
  .attr("transform","translate(150,150)rotate("+angle+")");
Comments