D3.js chain transitions for compound animations for different shapes

Jason McCreary picture Jason McCreary · Apr 3, 2013 · Viewed 12.4k times · Source

What I'm trying to do...

I'm toying with D3 to make a compound animation. I have the following final state:

enter image description here

Essentially I want to animation connecting the dots - add the first circle. Then draw the line to the second circle. Once the line is drawn, the second circle is added.

To add some visual appeal, I perform other transitions, such as changing circle radius for the first and second circle as the line is draw.

What I've tried...

I can add the circles and draw the line individually, including animations. However, I'm not sure how to proceed with chaining the transitions together to form the compound animation.

I've read about transitions/animations, which suggests using each("end"). While this would work to draw the initial objects, end doesn't fire until after the other transitions.

Questions

  • Is using each("end", ...) the correct approach for chaining transitions?
  • How do I start another animation (i.e. start draw the line) while still allowing another transition to complete (i.e. the first circle radius burst).

Answer

Biovisualize picture Biovisualize · Apr 3, 2013

The transition are easier to chain since d3.v3 without using "end". See the notes here.

For example, look at this one:

rect.transition()
  .duration(500)
  .delay(function(d, i) { return i * 10; })
  .attr("x", function(d, i, j) { return x(d.x) + x.rangeBand() / n * j; })
  .attr("width", x.rangeBand() / n)
  .transition()
  .attr("y", function(d) { return y(d.y); })
  .attr("height", function(d) { return height - y(d.y); });

That's for transitions on the same element. For different elements, look at this one.

// First transition the line & label to the new city.
var t0 = svg.transition().duration(750);
t0.selectAll(".line").attr("d", line);
t0.selectAll(".label").attr("transform", transform).text(city);

// Then transition the y-axis.
y.domain(d3.extent(data, function(d) { return d[city]; }));
var t1 = t0.transition();
t1.selectAll(".line").attr("d", line);
t1.selectAll(".label").attr("transform", transform);
t1.selectAll(".y.axis").call(yAxis);

The transition is attached to the svg element and chained from there.