A D3 transition animates a selected element from its current visual state to new attribute or style values. Chain transition() before the properties that should change over time; properties chained earlier are unaffected. Transitions make state changes easier to follow, helping viewers see what changed and where it moved. section 7.2.4
Animate a histogram update
Bind updated bins, call transition(), then set the bar y position and height. D3 interpolates those later values rather than making the bars jump directly to their new sizes. section 7.2.4
d3.selectAll("#histogram rect")
.data(updatedBins)
.transition()
.attr("y", d => yScale(d.length))
.attr("height", d => innerHeight - yScale(d.length));
The listing isolates the essential order: bind data, start a transition, then update the attributes to animate. section 7.2.4
Control timing with duration(milliseconds) and delay(milliseconds). Without configuration, D3 uses a 250 ms duration and no delay. Use ease() to control the rate of change: easing can start or end gradually and make movement feel more natural than a constant speed. section 7.2.4
Use transitions deliberately during data updates:
- Preserve element identity with a key function so circles that remain in a filtered scatterplot continue to represent the same datum. section 7.4.2
- Handle enter, update, and exit selections separately when new marks need distinct starting states or departing marks need an exit animation. section 7.4.2
- Create one d3.transition() value when enter and exit animations need the same duration and easing. section 7.4.3
Filter a cetacean scatterplot
A filter click updates the bound circle data. New circles can begin above the chart with radius 0 and opacity 0, then transition into position; retained circles keep their identities when data() receives each cetacean's uid as a key. section 7.4.2
Listing 7.14 Adding a reusable transition (interactions.js)
const handleClickOnFilter = (data) => {
d3.selectAll(".filter")
.on("click", (e, datum) => {
if (!datum.isActive) {
...
const t = d3.transition() #1
.duration(800)
.ease(d3.easeExpOut);
innerChart
.selectAll("circle")
.data(updatedData, d => d.uid)
.join(
enter => enter
.append("circle")
.attr("class", "cetacean")
...
.call(enter => enter.transition(t) #2
...,
update => update,
exit => exit
.call(exit => exit.transition(t)
...)
)
}
});
};
The listing defines an 800 ms exponential ease-out transition once, then passes it to enter and exit selections. section 7.4.3
When D3 shares an application with a frontend framework, transitions require D3 to manipulate the relevant DOM elements. For changes limited to CSS properties, CSS transitions, CSS animations, or react-spring can be preferable; transitioning an SVG path's d attribute is a case where D3 transitions can be especially practical. section 8.1 section 8.8
