Skip to content

Instantly share code, notes, and snippets.

@mbostock
Forked from mbostock/.block
Last active June 5, 2023 14:25
Show Gist options
  • Save mbostock/3808221 to your computer and use it in GitHub Desktop.
Save mbostock/3808221 to your computer and use it in GitHub Desktop.
General Update Pattern, II
license: gpl-3.0
redirect: https://observablehq.com/@d3/selection-join

By adding a key to the data-join, letters that are already displayed are put in the update selection. Now updates can occur anywhere in the array, depending on the overlap between the old letters and the new letters. The text content only needs to be set on enter because the mapping from letter to element never changes; however, the x-position of the text element must now be recomputed on update as well as enter.

It'll be easier to see what's going on when we add animated transitions next!

Next: Update Transitions

Previous: General Update Pattern

<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
font: bold 48px monospace;
}
.enter {
fill: green;
}
.update {
fill: #333;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", "translate(32," + (height / 2) + ")");
function update(data) {
// DATA JOIN
// Join new data with old elements, if any.
var text = g.selectAll("text")
.data(data, function(d) { return d; });
// UPDATE
// Update old elements as needed.
text.attr("class", "update");
// ENTER
// Create new elements as needed.
//
// ENTER + UPDATE
// After merging the entered elements with the update selection,
// apply operations to both.
text.enter().append("text")
.attr("class", "enter")
.attr("dy", ".35em")
.text(function(d) { return d; })
.merge(text)
.attr("x", function(d, i) { return i * 32; });
// EXIT
// Remove old elements as needed.
text.exit().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