我正在使用d3创建一个可视化,它将有60个顶部矩形和60个底部矩形。每个矩形将包含大约100-150个圆圈。数据通过websockets进行流式传输。没有过滤,更新是非常耗时的。我试图通过选择性更新来优化它。但是,看起来我还没有完全理解.filter()。这是处理矩形的代码部分的jsFiddle
正如你可以从函数updateRect中的js注释中看到的那样,我尝试了几种方法。 1.过滤.data 2.创建一个id并在id上执行selectAll。
但两种方法都不起作用。
关于我遗失或做错的任何帮助?
var bottom_rects = 1;
var top_rects = 1;
var rects = [];
function generate_rect(){
var created = '';
// 6(*10) top rectangles & 6(*10) bottom rectangles
if(bottom_rects <= top_rects-1) {
new_rect = {"name":"rect_bottom_"+bottom_rects,"location":"bottom","minx":0,"miny":Math.floor((2*h)/3),"maxx":0,"maxy":h};
rects.push(new_rect);
//fix x values
var step = Math.floor(w/bottom_rects);
var x = 0;
for (var i = 0; i < rects.length; i++) {
var item = rects[i];
if (item.location == "bottom"){
item.minx = x;
item.maxx = x+step;
x=x+step;
}
}
bottom_rects++;
created = "bottom";
} else {
new_rect = {"name":"rect_top_"+top_rects,"location":"top","minx":0,"miny":0,"maxx":0,"maxy":Math.floor(h/3)};
rects.push(new_rect);
//fix x values
var step = Math.floor(w/top_rects);
var x = 0;
for (var i = 0; i < rects.length; i++) {
var item = rects[i];
if (item.location == "top"){
item.minx = x;
item.maxx = x+step;
x=x+step;
}
}
top_rects++;
created = "top";
}
updateRect(created);
}
var w = 1200,
h = 760;
var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
function updateRect(location) {
//var allrects = vis.selectAll("rect")
var allrects = vis.selectAll(".rect_"+location)
//.data(rects.filter(function(d) { return d.location == location; }))
.data(rects)
//update
.attr("x", function(d) { return d.minx; })
.attr("y", function(d) { return d.miny; })
.attr("width",function(d) { return d.maxx-d.minx; })
.attr("height", function(d) { return d.maxy-d.miny; })
//create
.enter().append("rect")
.attr("x", function(d) { return d.minx; })
.attr("y", function(d) { return d.miny; })
//.attr("id", "rect_"+location)
.attr("width",function(d) { return d.maxx-d.minx; })
.attr("height", function(d) { return d.maxy-d.miny; })
.attr("fill", "blue")
.attr("stroke", "black")
.style("stroke-width", 2)
.style("fill-opacity", 0.2)
.exit().remove();
}
for(var i =0; i < 12; i++) setTimeout(generate_rect,(i+1)*200);
答案 0 :(得分:2)
有两种不同的filter()
功能。第一个是Javascript filter
,您可以将其应用于任何阵列,与D3无关。第二个是D3's filter
,您可以将其应用于选择。
对于选择性更新,您原则上可以使用两者。在第一种情况下,您将数据过滤到.data()
之前(正如您已经尝试过的那样),然后对与现有DOM元素匹配的内容进行操作。这里重要的是你几乎肯定需要为.data()
提供一个函数,告诉它如何将数组中的数据与DOM元素进行匹配。 the documentation中有更多内容。
对于你想要做的事情,我建议使用另一个.filter()
函数来操作选择。也就是说,您可以像通常情况一样选择,然后从该选择中过滤元素。对于您的示例,代码看起来像这样。
vis.selectAll("rect")
.filter(function(d) { return d.location == location; });
或者,您可以使用第三种按类选择的方法(您也尝试过),但是您不需要任何其他过滤功能。但是,如果要将新数据绑定到这些元素,则必须注意仅传递针对此特定元素子集的数据,即在将数据传递给{{1}之前需要过滤数据}。实际上,这可能是最不直观的方式,因为您需要在多个位置对数据进行分区。