D3 transitions let you smoothly animate between different chart states. This article shows how to add transitions to selection updates, how to set transition duration, how to create staggered transitions, how to change the easing function, how to chain transitions and how to create custom tween functions.
For example, let’s join an array of 5 numbers to SVG circles. When the ‘Update data’ button is clicked, the data is randomised and the circles jump to new positions:
If we add a transition to the circles the circles move smoothly to their new locations:
Furthermore, entering circles (circles that have just been created) and exiting circles (circles that are about to be removed) can be transitioned in specific ways. In this example new circles fade in and exiting circles drop down the page:
How to create a D3 transition
Creating a basic transition using D3 is fairly straightforward. Suppose you have the following code which joins an array of random data to
If you’re not familiar with the above code I suggest reading the data joins chapter.
updateAll function is called when a button is clicked:
updateData which randomises the
data array. It also calls
update which joins
When the button is clicked the circles jump to new locations:
You can then add a
.transition() call before the
.style methods that you wish to transition:
In this example, the
.transition call is followed by a single
.attr call. This results in the
cx attribute of the circles transitioning into new positions:
.transitionmethod returns a ‘transition selection’. This is basically the same as a normal D3 selection, except the
.stylemethods animate attributes and style. A transition selection has additional methods such as
.tweenwhich we’ll cover later.
.transition method has been called, subsequent calls to
.style will animate attributes and style, respectively.
For example, let’s randomise the radius and colour of each circle:
In the update function we update the radii and fills after the
Now when the data updates, the position, radius and colour of each circle transitions:
Duration and delay
You can change the duration of a transition by calling
.duration after the
.transition call. The
.duration method accepts an argument which specifies the duration in milliseconds:
In this example we’ve set the duration to 2000 milliseconds:
You can also specify a delay before which the transition starts:
The delay is usually used to delay each element in the selection by a different amount. For example, you can create staggered transitions by passing a function into
.delay and setting the delay to a multiple of the element index
An easing function defines the change in speed of an element during a transition. For example, some easing functions cause the element to start quickly and gradually slow down. Others do the opposite (start slowly and speed up) while others define special effects such as bouncing.
D3 has a number of built in easing functions which you can try out in this explorer:
In general ‘in’ refers to the start of the motion and ‘out’ refers to the end of the motion. Therefore,
easeBounceOutcauses the element to bounce at the end of the transition.
easeBounceInOutcauses the element to bounce at the start and end of the transition.
It’s usually better to use easings where the element moves quickly at first and slows down. For example
easeCubicOutis a commonly used easing function where the element moves quickly at first and slows down. D3’s default easing function is
easeCubicwhich is equivalent to
easeCubicInOut. This causes the element to start slowly, accelerate, then finish slowly.
To select an easing function use the
.ease method and pass in the easing function (e.g.
Transitions can be chained together by adding multiple calls to
.transition. Each transition takes it in turn to proceed. (When the first transition ends, the second one will start, and so on.)
For example, let’s chain two transitions. The first sets the
cx attribute and the second sets the
r attribute (and uses
When the chart updates, the circles move to their new positions, then the radius changes (with a bounce):
In most circumstances D3 is able to transition attributes and style in a sensible manner. However there are times where the default behaviour might not be suitable.
For example, suppose we join an array of angle values to
circle elements. Each circle is placed on the circumference of a larger circle using the joined value to determine where on the circle it sits. An angle of zero corresponds to 3 o’clock on the large circle.
When the data updates, the circles travel in a straight line:
You can customise the path the elements take (such as along the circumference of the large circle) by using a tween function.
To use a tween function, call the
.tween function at some point after
.transition. You pass a name (which can be anything you like) and a function into
The function gets called once for each element in the selection. It must return a tween function which will get called at each step of the transition. A time value
t between 0 and 1 is passed into the tween function. (
t is 0 at the beginning of the transition and 1 at the end.)
Typically you’ll set up interpolator function(s) in the outer function. An interpolator function takes a parameter between 0 and 1 and interpolates between two given values. The interpolator function can be used when updating HTML/SVG elements in the tween function.
In the function that’s passed into
.tween we start by computing
We then set up an interpolator function
i. This is a function that interpolates between two values (
targetAngle in our case). The function
i accepts a number between
1 and interpolates between the two values.
Next we create a tween function and return it. The tween function uses the interpolator function
i to compute
angle for the given time value
t. It then updates the
cy attributes using
angle. The tween function is called for each step of the transition.
Now when the button is clicked, the circle moves along the circumference of the large circle. Notice also that when the button is rapidly clicked, the transition starts from the circle’s current (mid-transition) position:
Entering and exiting elements
You can define specific transitions for entering and exiting elements. (Entering elements are newly created elements and exiting elements are ones that are about to be removed.)
For example you might want entering circles to fade in and exiting circles to fall:
To define enter and exit transitions you need to pass three functions into the
.join method. This was covered in the Enter, exit and update chapter so if you’re not familiar with these concepts I suggest you read up on them there.
As a brief reminder, you can pass three functions (instead of an element name) into the
The first, second and third functions are named the enter, update and exit functions, respectively.
As covered in Enter, exit and update chapter the enter function should append an element to each element of the enter selection.
You can also set the style and attributes of entering elements and this has the effect of initialising elements before any transitions take place.
opacity on entering circles:
The initial x and y coordinates of entering circles are initialised so that the circles appear in place (rather than sliding in from the origin).
The initial radius of entering circles is initialised so that the circles appear with a radius of 40.
Finally the opacity of entering circles is initialised to 0 so that entering circles fade in. (We’ll set the final opacity later on.)
The exit function usually removes the elements in the exit selection:
If you don’t call
.removeon the exit selection, the elements will remain on the page.
You can add a transition to exiting elements by calling
.transition on the exit selection. For example, to make exiting elements fall off the page, use
.transition and set the
cy attribute to a large value:
.remove method of a transition selection removes the selection’s element(s) when the transition ends.
You can apply a transition to entering and updating elements by adding a call to
.transition after the
.join call. This will cause all elements (except exiting elements) to transition.
Let’s add a
.transition call and set the
cx attribute and the
This has the following effect:
- when the data changes, the circles transition to new positions (because of
- when new circles are created, they fade in
The circles fade in because their initial opacity is set to zero in the enter function and the
.style call animates the opacity to 0.75.
Putting it all together
Here’s the complete example where:
- circles fade in (without sliding or expanding)
- circles transition to new positions
- circles fall off the page when they exit
- entering elements are initialised in the enter function. This is first function passed into
.join. This allows you to initialise style and attributes of entering elements (before the transition starts)
- a transition is applied to exiting elements in the exit function. This is the third function passed into
- entering and existing elements are transitioned by adding a call to
The update function (the second argument of
.join) only updates existing elements (and not entering elements) and I rarely add any special code here.