我正在使用d3.js开发一些图表。我只是写了一些功能来在屏幕上绘制一些线条。但我发现自己编写了重复代码来设置属性以进入选择和更新选择。更糟糕的是,这是不可避免的。
检查以下代码。最初,我觉得它很酷。每次更改输入数据时,我都可以调用此函数,图表将相应更新:如果有更多数据到来,将添加新行,如果只更改数据,则现有行将是重新绘制。
function drawLines(data){
svg.selectAll('line')
.data(data)
.enter()
.append('line')
.attr({
x1: function(d){
return d.x1;
},
y1: function(d){
return d.y1;
},
x2: function(d){
return d.x2;
},
y2: function(d){
return d.y2
}
})
.style({
stroke: 'black',
'stroke-width': 4
});;
}
但我发现它不起作用。追加方法不会同时返回更新+输入选择。我还在处理输入选择。所以我必须编写如下代码:
function drawLines(data){
var updateSelection = svg.selectAll('line')
.data(data);
var enterSelection = updateSelection
.enter()
.append('line');
enterSelection
.attr({
x1: function(d){
return d.x1;
},
y1: function(d){
return d.y1;
},
x2: function(d){
return d.x2;
},
y2: function(d){
return d.y2
}
})
.style({
stroke: 'black',
'stroke-width': 4
});
updateSelection
.attr({
x1: function(d){
return d.x1;
},
y1: function(d){
return d.y1;
},
x2: function(d){
return d.x2;
},
y2: function(d){
return d.y2
}
})
.style({
stroke: 'black',
'stroke-width': 4
});
}
正如您所看到的那样,我要复制attr,样式代码只是为了在输入选择和更新选择上执行相同的操作。但是d3.js文档的enter方法部分说:
在追加时,回车选择会合并到更新选择中 或插入。这种方法减少了输入和输入之间的代码重复 进行更新。而不是将运算符应用于输入和更新 单独选择,您现在可以将它们应用于更新选择 进入节点后。在极少数情况下你想运行 只有更新节点上的运算符,您可以在更新时运行它们 在输入新节点之前进行选择。
现在我对它的含义感到困惑"将选择合并到更新选择中#34;和"减少输入和更新之间的代码重复"。难道我做错了什么?据我了解,输入和更新之间的重复代码是不可避免的!
答案 0 :(得分:10)
文档的含义是,一旦附加元素,它们将成为更新选择的一部分。也就是说,您在更新选择上设置的任何属性也将在您之前输入选择中添加的元素上设置。所以你只需要以下代码:
var updateSelection = svg.selectAll('line')
.data(data);
updateSelection.enter().append('line');
updateSelection
.attr({
x1: function(d){
return d.x1;
},
y1: function(d){
return d.y1;
},
x2: function(d){
return d.x2;
},
y2: function(d){
return d.y2
}
})
.style({
stroke: 'black',
'stroke-width': 4
});
请注意,代码的顺序在这里很重要 - 您需要在设置更新选择的属性之前附加输入选择的元素。
答案 1 :(得分:0)
您可以删除.style以进行更新,但您需要保留x1,y1,x2,x2
原因是d3基于一个简单的原则:
在更新中,使用相同的键'像以前一样可以变换。所以,让我们说你有一个像这样的数据集:
[ { name: 'A', value: 2 } ]
它改为:
[ { name: 'A', value: 3 } ]
您需要以某种方式更新现有名称' A'从2到3。
这就是为什么你需要x1,x2,y1,y2才能更新。
希望这有帮助。