I'm having trouble when I try to correctly execute a rotation animation using the D3.js library. The problem has to do with the point at which I want to rotate the element about.
Here is a fiddle I made to show what I mean (in slow motion): http://jsfiddle.net/74mCb/
It seems like the source of the problem lies here:
.attr("transform", "rotate(-60, 150,130)");
And then I rotate it like so:
.attr("transform", "rotate(40 150,130)");
I would like the butt of the needle to stay in position (to be the center of rotation), could someone please explain what I am doing wrong?
Thanks!
This is a bit tricky to grasp (I don't fully understand it myself) but D3 needs some help knowing how to interpolate between the two strings that represent your rotation.
function turnNeedle()
{
needle
.transition()
.duration(2000)
.attrTween("transform", tween);
function tween(d, i, a) {
return d3.interpolateString("rotate(-60, 150, 130)", "rotate(60, 150, 130)");
}
}
d
is the datum, i
is the index, a
is the attribute in case you want to make this data-driven.
http://jsfiddle.net/SHF2M/
Here's what I think is going on: per the SVG spec, the transform
rotate(40 150,130)
is equivalent to:
translate(150,130) rotate(40) translate(-150, -130)
It looks like D3 is animating the translation as well as the rotation - the internal d3.transform
representation of rotate(40 150,130)
is a rotate component + a translation component, so both are being included in the transition.
The easiest fix here is to draw your needle at the origin, translate it with an outer g
element to the correct position, then rotate it:
var needle = svg
.append("g")
.attr("class", "needle")
.attr("transform", "translate(150 , 130)")
.append("path")
.attr("class", "tri")
// your path may have been prettier
.attr("d", "M-3 0 L0 -130 L3 0 S3 5 0 5 S-3 5 -3 0 Z")
.attr("transform", "rotate(-60)");
then
needle
.transition()
.duration(2000)
.attr("transform", "rotate(40)");
See working fiddle: http://jsfiddle.net/nrabinowitz/74mCb/1/