2

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.

red circle didn't get deleted, but went to background

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.

enter image description here

Community
  • 1
  • 1
Dmitry Shvedov
  • 3,169
  • 4
  • 39
  • 51
  • You need to make all modifications to the data (i.e. add and remove) before rerunning the pack layout and redrawing. – Lars Kotthoff Nov 17 '15 at 23:19
  • Tried that, please see the edit. – Dmitry Shvedov Nov 18 '15 at 15:17
  • You need to add *and* remove everything *before* running the pack layout and redrawing. – Lars Kotthoff Nov 18 '15 at 18:17
  • Oh ok, what I'm actually doing to produce those screenshots is: I'm not adding anything (basically you can just ignore that part of the code). The circle that you're seeing in both screenshots (sent to back or to front) is a circle that is being _removed_. In this particular instance there is nothing to add. – Dmitry Shvedov Nov 18 '15 at 19:15
  • Could you provide a complete example that allows to reproduce the problem please? – Lars Kotthoff Nov 18 '15 at 19:15

0 Answers0