当我使用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!
这段代码有什么问题?没有删除块它可以工作,但我需要它来处理新的/删除的项目。怎么做对了?
答案 0 :(得分:10)
问题在于您选择普通g
元素将数据绑定到(.selectAll('g').data(...)
)。当只有这些元素的一个级别时,这样可以正常工作,但是当.selectAll()
以递归方式工作时,它将选择比您拥有嵌套结构时想象的元素多得多的元素。
也就是说,选择包含更多元素,这些元素消耗了#34;绑定数据。因此,数据最终不会与正确的元素匹配。
要修复,只需使选择器更具体:
group = d3.select('.svg-content')
.selectAll('g.group-content')
.data(...);
完整演示here。