Published
Edited
Jan 22, 2020
1 star
d3 Selections with Updating Data
Insert cell
Insert cell
md`## Thingy 1`
Insert cell
chart = {
const height = 200;
const svg = d3.create("svg").attr("viewBox", [-width / 2, -height / 2, width, height]);
const nodes = [];
const nodeSelection = svg
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("cx", (d, i) => (i % 10) * 20)
.attr("cy", (d, i) => Math.floor(i / 10) *20)
.attr("r", 10)
.attr("fill", "teal");
for (let i = 0; i < 100; ++i) {
nodes.push({ id: i });
yield Promises.tick(4000, svg.node());
}
yield svg.node();
}
Insert cell
Insert cell
md`## Thingy 2`
Insert cell
nodes2 = {
const nodes = [];
for (let i = 0; i < 100; ++i) {
nodes.push({ id: i });
yield Promises.tick(4000, nodes);
}
}
Insert cell
chart2 = {
const height = 200;
const svg = d3.create("svg").attr("viewBox", [-width / 2, -height / 2, width, height]);
const nodeSelection = svg
.selectAll("circle")
.data(nodes2)
.join("circle")
.attr("cx", (d, i) => (i % 10) * 20)
.attr("cy", (d, i) => Math.floor(i / 10) *20)
.attr("r", 10)
.attr("fill", "teal");
yield svg.node();
}
Insert cell
Insert cell
chart3 = {
const height = 200;
const svg = d3.create("svg").attr("viewBox", [-width / 2, -height / 2, width, height]);
const nodes = [];
const nodeSelection = svg
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("cx", (d, i) => (i % 10) * 20)
.attr("cy", (d, i) => Math.floor(i / 10) *20)
.attr("r", 10)
.attr("fill", "teal");
for (let i = 0; i < 100; ++i) {
nodes.push({ id: i });
yield Promises.tick(4000, {svg,nodes});
}
yield {svg,nodes};
}
Insert cell
md`Here, we attempt the same strategy as in Thingy 1. However, unlike in Thingy 1, the cell that displays the svg node is separated from the cell in which the svg's contents are calculated. The thinking is that since cells "only run in response to _other cells_", we can trigger the re-draw simply by making sure the cell displaying the svg references something in a different cell.

When the cell executes a new iteration of the loop, it should yield a new value of the object \`{svg,nodes}\`. The dependent cells should then update as a result -- _but only if the new values are different_. In this case, \`nodes\` changes each iteration, but \`svg\` does not.
`
Insert cell
chart3.nodes
Insert cell
chart3.svg.node();
Insert cell
Insert cell
Insert cell
chart4 = {
const height = 200;
const svg = d3.create("svg").attr("viewBox", [-width / 2, -height / 2, width, height]);
const nodes = [];
for (let i = 0; i < 100; ++i) {
nodes.push({ id: i });
const nodeSelection = svg
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("cx", (d, i) => (i % 10) * 20)
.attr("cy", (d, i) => Math.floor(i / 10) *20)
.attr("r", 10)
.attr("fill", "teal");
yield Promises.tick(4000, {svg,nodes});
}
yield {svg,nodes};
}
Insert cell
chart4.svg.node();
Insert cell
d3 = require("d3@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more