Skip to content

Instantly share code, notes, and snippets.

@koshdnb
Forked from mbostock/.block
Created February 18, 2016 11:29
Show Gist options
  • Select an option

  • Save koshdnb/a35222ceb9abe562b95c to your computer and use it in GitHub Desktop.

Select an option

Save koshdnb/a35222ceb9abe562b95c to your computer and use it in GitHub Desktop.
General Update Pattern 4.0
license: gpl-3.0

This example shows two improvements to the General Update Pattern in D3 4.0. (The old pattern still works, but the new one is slightly more concise, efficient, and precise.)

The text elements only need to be selected once, when they are created, rather than for every update. That’s because selection.data now modifies the selection in-place:

// DATA JOIN
// Join new data with old elements, if any.
text.data(data, function(d) { return d; });

The transition timing parameters don’t need to be repeated for enter, update, and exit. Instead, a top-level transition sets the duration, and then subsequent transitions use selection.transition, passing in t to inherit timing:

var t = d3.transition()
    .duration(750);

(In fact, this fixes a bug in the 3.x pattern, where occasionally the transitions would be out-of-sync by a millisecond or two. In 4.0, transitions scheduled simultaneously are automatically synchronized using d3.now, even if you don’t explicitly pass a transition to selection.transition! This example also uses the new d3.interval to ensure that no transitions are run when the page is backgrounded.)

<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
font: bold 48px monospace;
}
.enter {
fill: green;
}
.update {
fill: #333;
}
.exit {
fill: brown;
}
</style>
<body>
<script src="//d3js.org/d3.v4.0.0-alpha.18.min.js"></script>
<script>
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(32," + (height / 2) + ")");
var text = svg.selectAll("text");
function update(data) {
var t = d3.transition()
.duration(750);
// DATA JOIN
// Join new data with old elements, if any.
text.data(data, function(d) { return d; });
// UPDATE
// Update old elements as needed.
text.attr("class", "update")
.attr("y", 0)
.style("fill-opacity", 1)
.transition(t)
.attr("x", function(d, i) { return i * 32; });
// ENTER
// Create new elements as needed.
text.enter().append("text")
.attr("class", "enter")
.attr("dy", ".35em")
.attr("y", -60)
.attr("x", function(d, i) { return i * 32; })
.style("fill-opacity", 1e-6)
.text(function(d) { return d; })
.transition(t)
.attr("y", 0)
.style("fill-opacity", 1);
// EXIT
// Remove old elements as needed.
text.exit()
.attr("class", "exit")
.transition(t)
.attr("y", 60)
.style("fill-opacity", 1e-6)
.remove();
}
// The initial display.
update(alphabet);
// Grab a random sample of letters from the alphabet, in alphabetical order.
d3.interval(function() {
update(d3.shuffle(alphabet)
.slice(0, Math.floor(Math.random() * 26))
.sort());
}, 1500);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment