I am trying to animate a set of points along with a path. Essentially I want to draw the path as the point appears, is there a way for them to have the same delay? I tried doing some calculations but the points seem to be plotted before the line gets to it. Here is a fiddle:
http://jsfiddle.net/Y62Hq/1/
And an excerpt of my code:
var totalLength = path.node().getTotalLength(); var duration = 7000; var interval = Math.round(duration/data.length); path .attr("stroke-dasharray", totalLength + " " + totalLength) .attr("stroke-dashoffset", totalLength) .transition() .duration(duration) .ease("linear") .attr("stroke-dashoffset", 0); var circles = svg.selectAll("circle") .data(data) .enter() .append("circle") .attr("fill", "blue"); circles .transition() .delay(function (d, i) { return i * interval;}) .ease("linear") .attr({ cx: function (d) { return yearScale(d.year); }, cy: function (d) { return window.innerHeight - numberScale(d.number)}, r: 4, fill: "blue", // /stroke: "#78B446", "stroke-width": 4 });
Hmm, intriguing. The problem is that not all of your line segments are the same length. While they all cover the same x distance, the y distance is different. Therefore, the amount of time the different line segments take to reach the next point differs. So you can't use a constant delay.
One way of doing this is to add and measure the different line segments, record their lengths and base the delay of the circles appearing on those lengths relative to the total length and the total duration.
var segments = [0]; for(var i = 1; i < data.length; i++) { var tmp = svg.append("path") .datum([data[i-1], data[i]]) .attr("d", line); segments.push(segments[i-1] + tmp.node().getTotalLength()); tmp.remove(); }
This code adds each line segment (from the first point to the second, second to third and so on), measures its length and removes it immediately afterwards. The result is accumulated in the array segments
, which gives the length of the total path up to this point (this is needed for the delay). This is why the previous length is added to the current length.
Then all you need to do to compute the delay for the points is
.delay(function (d, i) { return segments[i]*duration/totalLength;})
Complete demo here. This should work for any number of points/type of line.