10

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).
charleslparker
  • 1,904
  • 1
  • 21
  • 31
Jason McCreary
  • 71,546
  • 23
  • 135
  • 174
  • Someone who was trying to do essentially the same thing asked a question here a couple of days ago: http://stackoverflow.com/questions/15692910/queue-of-transitions-in-d3-js-one-by-one/15693534. I don't know if his approach is the most idiomatic approach, but it does work (but see my reply to his Q for the working jsFiddle link). – meetamit Apr 03 '13 at 18:43
  • Instead of explicitly chaining the transitions, you can also use the `delay()` function to delay the start of the subsequent animations until the previous ones have finished. – Lars Kotthoff Apr 03 '13 at 20:39
  • @meetamit, While close, it's not the same question. I'm still curious how to chain these together. He seems to have a set of animations, not necessarily dependent upon one another. – Jason McCreary Apr 03 '13 at 20:40
  • @Lars Kotthoff, I'll look into that. But keep in mind that some transitions run in parallel. So delay wouldn't necessarily work across the board. – Jason McCreary Apr 03 '13 at 20:41
  • It should as long as you can determine when each transition should start. If, for example, your line is drawn in 1 second, you would delay the transition drawing the second circle by that amount of time. – Lars Kotthoff Apr 03 '13 at 20:46
  • I get an error when attempting to append the line after the circle transition - `object has no method 'append'`. Why don't you leave a quick example as an answer so you can get some points. – Jason McCreary Apr 03 '13 at 20:53

1 Answers1

23

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.

Biovisualize
  • 2,455
  • 21
  • 20