Animated Declarative D3 Examples in React

Rowan 🤖
Technical Credit đź’¸
3 min readApr 28, 2018

The closing of the last post about declarative D3 in React mentioned that using the D3 transition API for animation was troublesome as it relied on DOM manipulations. This post will show how we can quite easily create our own transition API for basic animations.

With Ease

In many cases we don’t want our chart to just appear with all the data displayed, instead we want it to initially display with no data and then have an animation transition it into its final state with all the data. So the idea is pretty simple, for an animation of length n, initially start with all of our data at zero d₀ and then using an easing function we calculate the data at each interval of our animation dᵢ until we reach the end of animation where our data dₙ is in its final state.

D3 makes it easy for us by providing a series of easing functions in its d3-ease package. So all we need to do is setup our animation loop to call the easing function during designated animation frames. The easiest way to do this is to create an higher-order component (HOC) which handles the animation loop and passes the data dᵢ into our original D3 chart component.

Animate HOC

We can create the below animateWithEase.js HOC to help with our animations:

Animation HOC

The heavy lifting in this code is the function animationStep which is kicked off using requestAnimationFrame when the component mounts. The easing functions take a time t as an argument which is typically in the range [0,1] (0 represents the start of the animation and 1 represents the end). So one of the main jobs of animationStep is to calculate t as the animation completed percentage (using the current elapsed/total duration) and then calculate the data to plot at time t using the passed in function easeData. Since requestAnimationFrame typically gets called 60 time per second, it would be very slow to call easeData every frame, so it only calls it according to the specified interval. In the render function it will render the wrapped component with the appropriate data at time t by passing it down as a prop called data (this prop name can be changed using the dataPropName config option).

Example 1: Bar Chart

See the animation in action

Here our ease function easeData uses D3’s easeCubicInOut to “grow” the data on the chart along the y-axis.

Example 2: Multi-Series Line Chart

See the animation in action

In this example easeData behaves a little bit differently. It doesn’t use the ease function to modify the values of the items in the data array, instead it uses D3’s easeLinear in conjunction with slice to change the size of the array i.e. at t=0 the array will be empty, at t=0.5 the array will contain the first half of the original array, and at t=1 the array will contain all of the items. This results in the chart being animated across the x-axis.

Done?

This solution should cover animating basic charts with an x & y axis. If it falls apart for more complicated animations, then please post a reply and I can look into it.

--

--