D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
Andrew-Reid
Full window
Github gist
Nested Enter/Update/Exit with id
<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>
https://d3js.org/d3.v4.js