我在这里有一组我正在使用D3可视化的对象。我将每个对象绑定到一个组元素,并附加一个依赖于某些对象属性的SVG图形,大致如下:
var iconGroups = zoomArea.selectAll("g.icons")
.data(resources)
.enter()
.append("g")
var icons = iconGroups.append(function(d){
if(d.type == "Apple"){
return appleIcon;
}else if(d.type == "Orange"){
return orangeIcon;
})
等。现在我想用额外的一行扩展其中一些图标。我可以为每个数据点添加一个行元素,并将它们设置为仅在适用的地方可见,但由于我只想将它们添加到100个数据点中的一个,这似乎效率低下。有没有办法将SVG行绑定到只有d.type == "Apple"
?
答案 0 :(得分:1)
您可以为要选择的图标添加一个类(例如appleIcon),并在选择器中使用该类添加行。
答案 1 :(得分:1)
使用d3过滤器。
selection.filter(selector)
过滤选择,返回仅包含指定选择器为true的元素的新选择。
答案 2 :(得分:1)
我会为图标和线创建单独的选择,这样:
var iconGroups = zoomArea.selectAll('g.icons')
.data(resources);
iconGroups
.enter()
.append('g')
.classed('icons', true);
iconGroups.exit().remove();
var icons = iconGroups.selectAll('.icon').data(function(d) {return [d];});
icons
.enter()
.append(function(d) {
if(d.type === 'Apple'){
return appleIcon;
}else if(d.type === 'Orange'){
return orangeIcon;
}
}).classed('icon', true);
icons.exit().remove();
var lines = iconGroups.selectAll('.line').data(function(d) {
return d.type === 'Apple' ? [d] : [];
});
lines
.enter()
.append('line')
.classed('line', true);
lines.exit().remove();
.exit()。remove()的添加只是因为我总是添加它以确保更新更好。 :)
也许代码比.filter()长,但我一直使用以下结构,并且它更容易扩展。
编辑:apropos comment - 如果你需要传递索引,你应该在绑定数据中传递它们:
var iconGroups = zoomArea.selectAll('g.icons')
.data(resources.map(function(resource, index) {
return Object.create(resource, {index: index})
}));
(Object.create()仅用于不改变数据,你可以使用_.clone,Object.assign()或者只要它不打扰你就改变它)
然后您可以像访问它一样访问它:
lines.attr("x1", function(d){ console.log(d.index);})