Search code examples
d3.jstreemap

d3 treemap graphic don't recognize enter() and exit() data correctly


I'm trying to create dynamic treemap graphic with lovely d3.js library. Here are sample of my code

element = d3.select(element[0]);
var margin = 10,
  width = parseInt(element.style('width')) - margin * 2,
  height = parseInt(element.style('height')) - margin * 2;

var color = d3.scale.category10();

var canvas = d3.select('.treemap').append('svg')
  .attr('width', width)
  .attr('height', height)
  .attr('transform', 'translate(-.5,-.5)')
  .style('margin', margin);

var treemap = d3.layout.treemap()
  .size([width, height])
  .value(function(d) { return d.value; })
  .sticky(false);

function redraw(data) {
  d3.selectAll('.cell').remove();
  var treemapData = {};
  treemapData.children = data.map(function(d) {
      return {
        name: d.name,
        value: d.value
      };
  });

  var leaves = treemap(treemapData);

  var cells = canvas.selectAll("g")
    .data(leaves);

  var cellsEnter = cells.enter()
    .append('rect')
    .attr('class', 'cell')
    .attr('x', function(d) { return d.x; })
    .attr('y', function(d) { return d.y; })
    .attr('width', function(d) { return d.dx; })
    .attr('height', function(d) { return d.dy; })
    .attr('fill', function(d) { return d.children ? null : color(d.name); })
    .attr('stroke', "#fff")
    .style('fill-opacity', 0);

console.log(cells.exit(), cells.enter());
}

And here I have stucked. console.log() shows that whole new data are enter(), and none are exit() !

Input data presents like

[{value: 590, name:"A1"}, {...}, ...]

without root object field, so that's why I remapped data in treemapData object.

Тhanks that you at least spent your time for reading this post so far, hope you have any suggestions.

UDP. you can check working version of my code here: https://jsfiddle.net/qtbfm08k/


Solution

  • The following works:

    • remove d3.selectAll('.cell').remove();
    • use the code below

    See the fiddle: https://jsfiddle.net/b6meLedn/4/

      var cells = canvas.selectAll('.cell') //select all cells
       .data(leaves);        //map the data
    
      cells.exit().remove();  //remove old extra elements 
      cells.enter()
       .append('rect')        //create new rectangles as necessary
       .attr('class', 'cell')
    
      cells                   //take all cells (old cells that have new data+extra new cells)
       .attr('x', function(d) { return d.x; })
       ...