javascript 如何更新 d3.js 中的绑定数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27169375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 07:03:38  来源:igfitidea点击:

How to update bound data in d3.js?

javascriptd3.js

提问by keisuke

I want to update a network graph dynamically in D3.js. Now my code is:

我想在 D3.js 中动态更新网络图。现在我的代码是:

var color = d3.scale.category20();
var my_nodes = [{"cluster": 0, "x": 50,  "y": 50},
                {"cluster": 0, "x": 100, "y": 50},
                {"cluster": 1, "x": 100, "y":100}];
var vis = d3.select("body").append("svg").attr("width", 500).attr("height", 500);
var nodes = vis.selectAll("circle.node").data(my_nodes).enter().append("g")
               .attr("class", "node");
var circles = nodes.append("svg:circle")
                   .attr("cx", function(d) { return d.x; })
                   .attr("cy", function(d) { return d.y; })
                   .attr("r", 5)
                   .style("fill", function(d) {return color(d.cluster)});

This code works. But when I update data like:

此代码有效。但是当我更新数据时:

var new_nodes = [{"cluster": 0, "x": 50,  "y": 50},
                 {"cluster": 2, "x": 100, "y": 50},
                 {"cluster": 2, "x": 100, "y":100}];
nodes.data(new_nodes);

doesn't work.

不起作用。

How can I update bound data?

如何更新绑定数据?

EDIT: What I want to do is replacing old data my_nodeswith new data new_nodes. Is there any way to update the attribute clusterof each bound data?

编辑:我想做的是用my_nodes新数据替换旧数据new_nodes。有没有办法更新cluster每个绑定数据的属性?

EDIT2: Suppose I do:

EDIT2:假设我这样做:

d3.select("body").select("svg").selectAll("circle").data(mydata).enter().append("svg:circle");

d3.select("body").select("svg").selectAll("circle").data(mydata).enter().append("svg:circle");

Can I modify mydata?

我可以修改mydata吗?

回答by Mark

There's no data-binding magic à la angular that's going to trigger a "redraw". Just call .dataand then re-set the attributes:

没有数据绑定魔法 à la angular 会触发“重绘”。只需调用.data然后重新设置属性:

function update(){
 nodes
  .attr("cx", function(d) {
    return d.x;
  })
  .attr("cy", function(d) {
    return d.y;
  })
  .attr("r", 5)
  .style("fill", function(d) {
    return color(d.cluster)
  });
}

var nodes = vis.selectAll("circle.node").data(my_nodes)
  .enter()
  .append("g")
  .attr("class", "node")
  .append("svg:circle");
update();

// some time later

nodes.data(new_nodes);
update();

Example here.

示例在这里

回答by Henry S

Not sure how you'd want this to look, but I've created a fiddle here: http://jsfiddle.net/henbox/8ua144p4/4/

不确定您希望它看起来如何,但我在这里创建了一个小提琴:http: //jsfiddle.net/henbox/8ua144p4/4/

Clicking the updatebutton will update to the new data.

单击该update按钮将更新为新数据。

I've based the changes off the General Update Patternsand this article from Mike on Joins

我已经根据一般更新模式Mike 在 Joins 上的这篇文章进行了更改

I've put a transition on the fillattribute for each circle, so you can hopefully see that the nodes are being updated in this case rather than new nodes being added. I've also shown a 4th new node being added, to demo the difference.

我已经fill为每个圆圈的属性设置了一个过渡,因此您可以看到在这种情况下节点正在更新,而不是添加新节点。我还展示了添加的第 4 个新节点,以演示差异。

Finally, I've simplified things a little by removing the node(g) elements and just using circle. This is the important code:

最后,我通过删除node( g) 元素并仅使用circle. 这是重要的代码:

// DATA JOIN
// Join new data with old elements, if any.
var circle = vis.selectAll("circle").data(data);

// ENTER
// Create new elements as needed.
circle.enter().append("svg:circle").attr("r", 5);

// UPDATE
// Update old elements as needed.
circle.attr("cx", function (d) {return d.x;})
    .attr("cy", function (d) {return d.y;})
    .transition().duration(750)
    .style("fill", function (d) {
    return color(d.cluster)
});
// EXIT
// Remove old elements as needed.
circle.exit().remove();

When the data is updated, force.start();is run everytime so it looks like new data. If you remove that, it's easier to see what's happening but you lose the animation. What you probably want is to only animate entry for the new nodes (and maybe exiting nodes), but that would be a separate question

当数据更新时,force.start();每次都运行,所以它看起来像新数据。如果你删除它,更容易看到发生了什么,但你失去了动画。您可能想要的是只为新节点(以及可能退出节点)设置动画,但这将是一个单独的问题