Mike Bostock has great example of a multi-series linechart here, which draws three series using compact code. Rather than drawing each line individually from the raw data, he creates a new data object ("cities") to iterate over, then draws all three path elements in one go:
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
[... etc] But suppose we wanted to animate this chart, so that each city's line "unrolled" one after another? Is such a thing possible, using Bostock's data structure?
First we'd create a tween function to unroll the lines smoothly (as demonstrated in this question). Something like:
function animateLine() {
var l = this.getTotalLength();
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) { return i(t); };
};
But if we invoked this animation as a transition in Mike Bostock's line-drawing code, wouldn't it just unroll all three lines simultaneously, rather than one after another?
I can see a hacky solution, which would be to define three separate (but basically identical) functions to draw each line one at a time, based on some lightly modified raw data...
var AustinLine = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.austin); });
var NewYorkLine = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.newyork); });
... [etc.] called in three separate line-drawing functions, invoking our "animateLine" function –
function AustinPath () {
var line = svg.append("path")
.datum(data)
.attr("d", AustinLine)
.transition()
.duration(2000)
.ease("linear")
.attrTween("stroke-dasharray", animateLine);
... [repeated twice more for the other cities: NewYorkPath and SanFranciscoPath]...
... then finally invoke these functions one after another, with the appropriate delays, to draw the lines one by one.
setTimeout(Austinpath, 500);
setTimeout(NewYorkPath, 2500);
setTimeout(SanFranciscoPath, 4500);
... [etc.]
This would unroll each line one by one, but the repetition in the code is mind-boggling, and totally contrary to the elegance of Mike Bostock's original example.
I know the hacky solution is terrible... but is there a more elegant alternative? Can Mike Bostock's original "enter().append" method be staggered, to draw three separate lines in turn?
Any suggestions greatly appreciated. Thanks in advance.