[英]d3 v4 update/merge grouped data
I am trying to update data for a force simulation in D3 v4, similar to this unsuccessful attempt and semi-similar to this successful one . 我想对于力模拟D3 V4,类似的数据更新这个不成功的尝试和半类似这种成功的一个 。 CodePen here CodePen 在这里
Instead of joining the new nodes it appears to be doubling all the nodes (see pictures). 与其加入新节点,不如将所有节点加倍(参见图片)。 It does not seem to be refreshing the graph correctly either. 似乎也无法正确刷新图表。
HTML: HTML:
<button onclick="addData()">Add Data</button>
<svg width="960" height="600"></svg>
JavaScript: JavaScript的:
function addData() {
graph.nodes.push({"id": "Extra1", "group": 11},{"id": "Extra2", "group": 11})
graph.links.push({"source": "Extra1", "target": "Valjean", "strength": 1},{"source": "Extra1", "target": "Extra2", "strength": 2})
update()
simulation.restart()
}
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var link, linkEnter, nodeWrapper, nodeWrapperEnter;
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.on("tick", ticked);
var allLinkG = svg.append("g")
.attr("class", "allLinkG")
var allNodeG = svg.append("g")
.attr("class", "allNodeG")
update()
simulation.restart()
function update(){
link = allLinkG
.selectAll("line")
.data(graph.links, function(d){ return d.id })
link.exit().remove()
linkEnter = link
.enter().append("line");
link = linkEnter.merge(link).attr("class","merged");
nodeWrapper = allNodeG
.selectAll("nodeWrapper")
.data(graph.nodes, function(d) { return d.id; })
nodeWrapper.exit().remove();
nodeWrapperEnter = nodeWrapper.enter()
.append("g").attr("class","nodeWrapper")
.append("circle")
.attr("r", 2.5)
nodeWrapper = nodeWrapperEnter
.merge(nodeWrapper).attr("class","merged");
simulation
.nodes(graph.nodes);
simulation.force("link")
.links(graph.links);
}
function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
nodeWrapper
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
Thanks very much for any help. 非常感谢您的帮助。
A few issues here: 这里有几个问题:
selectAll
is selecting by element type nodeWrapper
, you meant by class .nodeWrapper
. 您的selectAll
是按元素类型nodeWrapper
选择的,而您的选择是类.nodeWrapper
。 .merge
, you can't do this as it breaks future selections by .nodeWrapper
class. 您在.merge
之后将类名称更改为“ merged”,则无法执行此操作,因为它会破坏.nodeWrapper
类将来的选择。 .merge
your selection, you are merging circle
s with g
s. 当你.merge
您的选择,您合并circle
以s g
秒。 You should stay consistent and operate on the g
s only. 您应保持一致并仅在g
s上操作。 Quick refactor: 快速重构:
function update() {
link = allLinkG
.selectAll("line")
.data(graph.links, function(d) {
return d.id
})
link.exit().remove()
linkEnter = link
.enter().append("line");
link = linkEnter.merge(link).attr("class", "merged");
nodeWrapper = allNodeG
.selectAll(".nodeWrapper") //<-- class nodeWrapper
.data(graph.nodes, function(d) {
return d.id;
})
nodeWrapperEnter = nodeWrapper.enter()
.append("g").attr("class", "nodeWrapper"); //<-- enter selection should be gs
nodeWrapperEnter //<-- append your circles
.append("circle")
.attr("r", 2.5)
nodeWrapper = nodeWrapperEnter //<-- merge, don't change class
.merge(nodeWrapper);
nodeWrapper.exit().remove(); //<-- and the exit
simulation
.nodes(graph.nodes);
simulation.force("link")
.links(graph.links);
}
Note , I also modified your tick
function to operate on the g
instead of the circle
: 注意 ,我还修改了您的tick
函数,使其在g
而不是circle
上进行操作:
nodeWrapper
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.