My problem is similar to this one: D3 update circle-pack data new nodes overlap existing nodes
I'm trying to dynamically update circle pack as the new data comes in. Here's my initialization code:
var pack = d3.layout.pack()
.size([packSize, packSize])
.value(function(d) { return d.size; });
var svg = d3.select('#svg_' + zone.id);
svg.selectAll('*').remove();
svg = svg.attr('width', diameter)
.attr('height', svg_height)
.append('g')
.attr('transform', 'translate(2,20)');
var node = svg.datum(d3data).selectAll('.node')
.data(pack.nodes, function(d) {return d.id;})
.enter().append('g')
.attr('class', function(d) { return d.children ? 'node' : 'leaf'; });
Here's my update code that gets called every second:
if (childrenToAdd.length > 0) {
for (var cIdx = 0; cIdx < childrenToAdd.length; cIdx++) {
map.data.children.push(d3CreateCirclePackChildData(zone.children[childrenToAdd[cIdx]]));
}
svg.datum(map.data).selectAll('.node')
.data(pack.nodes, function(d) {return d.id;})
.enter().append('g')
.attr('class', function(d) { return d.children ? 'node' : 'leaf'; });
}
if (childrenToRemove.length > 0) {
for (var rIndex = 0; rIndex < childrenToRemove.length; rIndex++) {
map.data.children.splice(childrenToRemove[rIndex], 1);
}
svg.datum(map.data).selectAll('.node')
.data(pack.nodes, function(d) {return d.id;})
.exit().remove();
}
The symptoms: the code to add a child doesn't produce anything useful. The code to remove a child works partially - the circle is removed from circle pack - so the outer circle shrinks and the child circles snap together, but the circle that is to be removed, still stays in the svg and is drawn behind the other child circles.
If I add modify the last part like so:
if (childrenToRemove.length > 0) {
for (var rIndex = 0; rIndex < childrenToRemove.length; rIndex++) {
map.data.children.splice(childrenToRemove[rIndex], 1);
}
map.pack = d3.layout.pack()
.size([packSize, packSize])
.value(function(d) { return d.size; });
svg.datum(map.data).selectAll('.node')
.data(pack.nodes, function(d) {return d.id;})
.exit().remove();
}
The removed circle is now sent to front instead.