Animated Declarative D3 Examples in React
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:
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.