Synthesis : Scott Becker

Learning D3 Part 3: Animation & Interaction

In Learning D3 Part 2, I went over how to bind datasets to the DOM, and get elements on and off the page with enter and exit sub-selections. This time I’ll go over how to add some basic animation and interaction.

Transitions

You specify animations (or other transitions) with the .transition() method, followed by a chain describing the end result. This can include any DOM transformation, such as updates to the width or background color. D3 conveniently calculates the “tween” values for distances and colors, which saves a huge amount of time. You just worry about the values to transition from and to, the duration of the animation, and any delay that should happen before the animation starts.

If you’re drawing a horizontal bar chart of running distances, it might help to convey distance a bit more by animating the growth of each bar horizontally.

var distances = [2.23, 2.39, 2.59, 2.77, 3.05];
 
d3.select('body').selectAll('div')
  .data(distances)
  .enter()
  .append('div')
  .html('.')
  .style('width', '10px')
  .style('opacity', 0)
  .transition()
    .delay(function(d, i) { return i * 1000 })
    .duration(1000)
    .style('width', function(d) { return (d * 150) + 'px'; })
    .style('opacity', 1)
    .text(function(d) { return d + ' miles'; });

I’m throwing in a few things at once. See it run here. What’s happening? A div is appended for each distance, and initially set to a small width of 10px, the text of “.” and an opacity of 0. It’s invisible! But only for a moment. Then we set up the transition. Each item is delayed 1 second later than the previous using a function returning a multiple of the item index. The duration is set to 1 second with .duration(1000). With this combo, each bar appears in succession. The rest is familiar, setting the full width, label text, and full opacity.

Interaction

Now let’s add some basic user interaction to it, by highlighting the current run when you mouse over it.

var distances = [2.23, 2.39, 2.59, 2.77, 3.05];
 
d3.select('body').selectAll('div')
  .data(distances)
  .enter()
    .append('div')
    .html('...')
    .style('width', '10px')
    .style('opacity', 0)
    .on("mouseover", function(){
      d3.select(this).transition().duration(300)
        .style("background-color", "#FFD700");
    })
    .on("mouseout", function(){
      d3.select(this).transition().duration(300)
        .style("background-color", "#333");
    })
    .transition()
      .delay(function(d, i) { return i * 300 })
      .duration(300)    
      .style('width', function(d) { return (d * 150) + 'px'; })
      .style('opacity', 1)
      .text(function(d) { return d + ' miles'; });

Here’s the running example. Notice the .on(“mouseover”) and .on(“mouseout”) events, describing another transition/animation to fade the background color to yellow and back. The events pass the current context as “this”, which you can again select with d3.select() and apply transitions to.

That’s the basic idea. These basic building blocks are all you really need to build up complex visualizations. I haven’t touched on SVG yet, so that’ll be up next.

 

One Response to “Learning D3 Part 3: Animation & Interaction”

  1. Kent says:

    Really enjoying your examples, so thanks so much for documenting your exploration. I hope to incorporate some of this in some blog posts soon. For now, I have a super simple silly example at http://axysreporting.com/fred-example.html. With the help of your examples, I hope to make it much more attractive and robust d3.js visualization.

Leave a Reply