Last active
October 9, 2022 11:10
-
-
Save Andrew-Reid/960819e98873bbaf035bbf6bd2774b40 to your computer and use it in GitHub Desktop.
Nested Enter/Update/Exit with id
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
</head> | |
<body> | |
<script> | |
// starter data: | |
var data = [ | |
{id:0, children: d3.range(10)}, | |
{id:1, children: d3.range(6)}, | |
{id:2, children: d3.range(9)}, | |
]; | |
var index = 3; // current parent index. | |
var t = 1000; | |
var svg = d3.select("body") | |
.append("svg") | |
.attr("width",600) | |
.attr("height",400) | |
// .on("click",update); | |
update(); | |
function update() { | |
manipulateData(); | |
var parents = svg.selectAll(".parentGroup") | |
.data(data, function(d) { return d.id; }); | |
// used for spacing: | |
var exiting = parents.exit().size(); | |
// transition child rects from parents that are exiting: | |
parents.exit() | |
.select(".childGroup") | |
.selectAll("rect") | |
.transition() | |
.attr("height",0) | |
.duration(t); | |
parents.exit().transition().style("fill","white").duration(t).remove(); | |
// enter new parents: | |
var parentsEnter = parents.enter() | |
.append("g") | |
.attr("class","parentGroup") | |
.attr("transform",function(d,i) { | |
return "translate(10,"+((i+exiting)*24+20)+")"; | |
}) | |
.style("fill", function(d) { return d3.schemeCategory20[d.id%20]; }); | |
// add child elements only to parents that were just entered: | |
parentsEnter.append("text") | |
.text(function(d) { return d.id; }); | |
parentsEnter.append("g") | |
.attr("class","childGroup") | |
// merge entered parents with pre-existing: | |
parents = parentsEnter.merge(parents); | |
// update all: | |
parents.transition().attr("transform",function(d,i) { return "translate(10,"+(i*24+20)+")"; }).duration(t); | |
// Select a child group in each parent: | |
var children = parents.select(".childGroup"); | |
// do an enter/exit/update cycle with the child's datum: | |
var childRects = children.selectAll("rect") | |
.data(function(d) { return d.children; }, function(d) { return d; }); | |
// rects removed individually: | |
childRects.exit() | |
.transition() | |
.attr("width",0) | |
.attr("height",0) | |
.duration(t) | |
.remove(); | |
// enter: | |
var childRectsEnter = childRects.enter() | |
.append("rect") | |
.attr("x", function(d,i) { return i * 24 + 30 }) | |
.attr("y", 4) | |
.attr("height",0) | |
.attr("width",20) | |
.transition() | |
.attr("height",20) | |
.attr("y",-16) | |
.duration(t); | |
// update pre-existing child rects: | |
childRects | |
.transition() | |
.attr("x", function(d,i) { return i * 24 + 30 }) | |
.duration(t); | |
} | |
setInterval(update,1200); | |
// modify data array in some randomish way: | |
function manipulateData() { | |
data.forEach(function(d,i) { | |
var r = Math.random(); | |
// remove parent sometimes | |
if (r > 0.8 && data.length > 2) { | |
data.splice(i,1); | |
} | |
// modify children sometimes (remove random element): | |
else if (r > 0.5) { | |
var length = d.children.length; | |
var remove = Math.floor(Math.random() * length); | |
d.children.splice(remove,1); | |
} | |
// modify children sometimes (add random element): | |
else if (r > 0.2) { | |
var max = d3.max(d.children, function(d) { return d; }); | |
d.children.push(max+1); | |
} | |
// add new parent sometimes: | |
else { | |
var n = Math.floor(Math.random()*10)+1; | |
data.push({ | |
id: index++, children: d3.range(n) | |
}) | |
} | |
}) | |
} | |
</script> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment