Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active February 9, 2016 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mbostock/10520338 to your computer and use it in GitHub Desktop.
Save mbostock/10520338 to your computer and use it in GitHub Desktop.
Interrupting Chained Transitions
license: gpl-3.0

This example demonstrates how to interrupt chained transitions. Normally when a chained transition ends, it immediately schedules the next transition. However, blindly scheduling the next chained transition can prevent a different, non-chained transition from taking over — such as the “Stop The Music” button here.

To ensure that a chained transition does not interrupt a different transition, you can check the number of scheduled transitions on the current element: this.__transition__.count. Normally during a chained transition, only one transition will be scheduled; if two transitions are scheduled, then the chained transition should stop.

D3 uses this check internally to implement transition.remove.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
position: relative;
width: 960px;
height: 500px;
}
button {
position: absolute;
cursor: pointer;
top: 50%;
left: 50%;
margin-top: -1.75em;
margin-left: -6em;
width: 12em;
padding: 1em 2em;
background: #000;
color: #fff;
border-radius: 8px;
border: solid 2px #fff;
font: 16px "Helvetica Neue", sans-serif;
}
button:focus {
outline: none;
}
button:hover {
text-shadow: 0 1px 0 #000;
background: #444;
}
button:active {
background: #222;
}
</style>
<button>Stop The Music</button>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500,
size = 80;
var color = d3.scale.ordinal()
.range(["#333", "brown", "white", "green", "steelblue"]);
var button = d3.select("button")
.on("click", click);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(-40,-30)");
var rect = svg.selectAll("rect")
.data(d3.merge(d3.range(0, width + size, size).map(function(x) {
return d3.range(0, height + size, size).map(function(y) {
return [x, y];
});
})))
.enter().append("rect")
.attr("transform", function(d) { return "translate(" + d + ")"; })
.attr("width", size)
.attr("height", size)
.style("stroke", "black")
.style("stroke-width", "2px")
.style("fill", "#000")
.on("click", pulse);
rect.transition()
.duration(0)
.delay(function(d, i) { return i * 5; })
.each(pulse);
function pulse() {
var rect = d3.select(this);
(function loop() {
rect = rect.transition()
.duration(750)
.style("fill", color(Math.random() * 5 | 0))
.each("end", function() { if (this.__transition__.count < 2) loop(); });
})();
}
function click() {
rect.transition()
.duration(750)
.delay(function(d, i) { return i * 5; })
.style("fill", "#333");
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment