Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active Sep 3, 2017
Embed
What would you like to do?
Concurrent Transitions
license: gpl-3.0

D3 transitions are exclusive and per-element. This typically means that you can’t run multiple transitions concurrently on the same elements; only the last-scheduled transition will run. However, since you can define custom tweens that run arbitrary code during transitions, you can decouple the transition’s element and the transition’s behavior if needed.

In this example, two transitions operate concurrently on the same path element. This works because the two transitions, twizzle and plonk, are created on dummy objects (twizzleLock and plonkLock, respectively) rather than the path element they manipulate.

An alternative approach is to schedule concurrent transitions on parent and child elements.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
fill: black;
stroke: red;
stroke-linejoin: round;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500;
var twizzleLock = {},
plonkLock = {};
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")")
.append("path")
.attr("d", d3.svg.symbol().type("cross").size(50000))
.call(twizzle, 20000)
.call(plonk, 2000);
function twizzle(path, duration) {
d3.select(twizzleLock).transition()
.duration(duration)
.tween("attr:transform", function() {
var i = d3.interpolateString("rotate(0)", "rotate(720)");
return function(t) { path.attr("transform", i(t)); };
});
setTimeout(function() { twizzle(path, duration); }, (Math.random() + 1) * duration);
}
function plonk(path, duration) {
d3.select(plonkLock).transition()
.duration(duration)
.tween("style:stroke-width", function() {
var i = d3.interpolateString("0px", "30px");
return function(t) { path.style("stroke-width", i(t)); };
})
.transition()
.tween("style:stroke-width", function() {
var i = d3.interpolateString("30px", "0px");
return function(t) { path.style("stroke-width", i(t)); };
});
setTimeout(function() { plonk(path, duration); }, (Math.random() + 2) * duration);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment