我正在使用d3.js使用强制布局布局节点和链接图。节点用圆圈表示;按行链接。在某些情况下,我想改变线或节点的视觉特性(例如,颜色,大小,不透明度等)以表示图上的一些状态变化。我已经能够通过重新绘制图形来实现这一点,但是这会使所有节点发生抖动,从而导致混淆而不是清晰。
创建图表的代码:
force = d3.layout.force()
.charge(-120)
.gravity(0.2)
.linkDistance(30)
.size([width-pad, height-pad]);
nodeSet = svg.selectAll(".qNode");
// BIND NODE DATA
nodeSet = nodeSet.data(chartData.nodes);
// CREATE NODES
nodeSet.enter().append("circle")
.attr("class", "qNode")
.attr("r", function(d) { return d.size();})
.style('stroke-opacity', function(d) { return d.opacity(); })
.style('stroke', function(d) { return d.color(); })
.style("fill", function(d) { return color(1); });
//similarly for links.
force.nodes(chartData.nodes).links(chartData.links).start();
要更新图表,我使用此片段:
// SELECT NODES
nodeSet = svg.selectAll('.qNode');
// JOIN NODES
nodeSet = nodeSet.data(force.nodes());
// UPDATE NODES
nodeSet.attr("class", "qNode")
.attr("r", function(d) { return d.size();})
.style("fill", function(d) { return color(1); })
.style('stroke', function(d) { return d.color(); })
.style('stroke-opacity', function(d) { return d.opacity(); })
.style('opacity', 1)
.call(force.drag);
// CREATE NODES
nodeSet.enter().append("circle")
.attr("class", "qNode")
.attr("r", function(d) { return d.size();})
.style("fill", function(d) { return color(1); })
.call(force.drag);
// DELETE NODES
nodeSet.exit().remove();
// START SHOW
force.start();
当它运行时,整个图形会稍微摇晃一下,然后再应用新的笔触属性。
所以我有两个问题:假设数据对象中的状态更改将返回d.size()
,d.color()
等的不同值,
EDITED
我暂时放弃了对节点的抖动,但下面的代码(基于@defenestrated的建议)似乎可以更新图中某些节点和边缘的属性:
var allLinks = ... // my links from a d3 selectAll
var allNodes = ... // my nodes from a d3 selectAll
force = ... // my d3 force layout
function updateGraph(graph, nodeSubset, linkSubset) {
for (var i=0; i<allLlinks.length; i++)
allLinks[i].selected = false;
for (var i=0; i<allNodes.length; i++)
allNodes[i].selected = false;
for (var i=0; i<linkSubset.length; i++)
linkSubset[i].selected = true;
for (var i=0; i<nodeSubset.length; i++)
nodeSubset[i].selected = true;
// these functions modify the selected nodes and links
linkSubset.call(setLinkAttributes);
nodeSubset.call(setNodeAttributes);
if (force.alpha() == 0) {
force.start();
force.stop();
}
}
function setLinkAttributes(links) {
link.style(...);
}
function setNodeAttributes(nodes) {
nodes.style(...);
}
如果图表在应用属性后仍在移动(如果start
),则无需致电stop
/ resume
或alpha() > 0
新属性。如果图表已经稳定,则调用start会刷新它而不移动节点。
答案 0 :(得分:1)
您是否尝试在“更新节点”块之前调用force.stop()
,并在{1}之后调用{<1}}?
您可以根据其状态对它们进行分类 - 因此您将force.resume()
应用于正在更新的节点,然后在d3选择中使用它,例如。 changedNodes = .attr("id", "changed")