d3.js:输入(),更新,退出(),其中包含组元素

时间:2014-12-16 08:44:30

标签: javascript d3.js

当我使用D3.js渲染我的可视化并输入,更新,退出模式时,我的DOM结构如下所示:

g
  rect
  ...
g
  rect
  ...
g
  rect
  ...

我正在处理我的组中的多个元素和嵌套选择,但为了简单起见,我将使用rects演示这一点。 DOM通过以下方式完成:

group = d3.select('.svg-content')
    .selectAll('g')
    .data(items, function (item) { return item.Id; });

groupEnter = group.enter()
    .append('svg:g')
    .attr('class','group-content');

// enter
groupEnter.append('svg:rect')
    .style('fill', '#000')
    .attr('x', function (item) { return item.x })
    .attr('y', function (item) { return item.y; })
    .attr('width', function (item) { return item.width; })
    .attr('height', function (item) { return item.height; });

// update
group.select('rect') 
    .attr('x', function (item) { return item.x })
    .attr('width', function (item) { return item.width; });

// remove
group.exit().remove();

这有效!

现在我想实现以下目标:

g
  g
    rect
  ...
g
  g
    rect
  ...
g
  g
    rect
  ...

我想将rect封装在另一个组元素中。

group = d3.select('.svg-content')
    .selectAll('g')
    .data(items, function (item) { return item.Id; });

groupEnter = group.enter()
    .append('svg:g')
    .attr('class','group-content');

// enter
groupEnter
    .append('svg:g') // NEW
    .attr('class','rect-content') // NEW
    .append('svg:rect')
    .style('fill', '#000')
    .attr('x', function (item) { return item.x })
    .attr('y', function (item) { return item.y; })
    .attr('width', function (item) { return item.width; })
    .attr('height', function (item) { return item.height; });

// update
group
    .select('.rect-content') // NEW
    .select('rect') 
    .attr('x', function (item) { return item.x })
    .attr('width', function (item) { return item.width; });

// remove
group.exit().remove(); // NOTE: without this, it works!

这段代码有什么问题?没有删除块它可以工作,但我需要它来处理新的/删除的项目。怎么做对了?

1 个答案:

答案 0 :(得分:10)

问题在于您选择普通g元素将数据绑定到(.selectAll('g').data(...))。当只有这些元素的一个级别时,这样可以正常工作,但是当.selectAll()以递归方式工作时,它将选择比您拥有嵌套结构时想象的元素多得多的元素。

也就是说,选择包含更多元素,这些元素消耗了#34;绑定数据。因此,数据最终不会与正确的元素匹配。

要修复,只需使选择器更具体:

group = d3.select('.svg-content')
    .selectAll('g.group-content')
    .data(...);

完整演示here