我正在研究基本的javascript D3图形类,该类可用于快速启动项目。当前添加链接和节点可以正常工作,但是我显然对某些基本概念不了解。
这是我当前正在删除节点的操作。
this.nodesRef = this.svg.select(".nodes").selectAll(".node");
//...
removeNode (iNodeId)
{
let indexToRemove = this.nodesData.map(node => node.id).indexOf(iNodeId);
this.nodesData.splice(indexToRemove,1);
this.nodesRef.data(this.nodesData,d => d.id).exit().remove();
};
我处理nodesRef
选择和nodesData
数组的方式显然存在问题。发生removeNode()
时,它看起来 正常,但所选内容仍然包含已删除的节点,并且当我稍后添加另一个节点时,添加的节点没有出现,一个节点被卡住,并且其他一些问题。
我需要弄清楚删除后如何正确更新选择内容和数据,但是老实说我迷失在输入/退出/更新语言中。
更新:
我添加了updateSimulation()
函数中缺少的removeNode()
,但是仍然存在一个问题,即删除后第6个节点本身无响应,但由第5个节点控制。
removeNode (iNodeId)
{
// Remove from data
let indexToRemove = this.nodesData.map(node => node.id).indexOf(iNodeId);
this.nodesData.splice(indexToRemove,1);
this.nodesRef.data(this.nodesData,d => d.id).exit().remove();
this.updateSimulation();
};
updateSimulation ()
{
this.simulation.nodes(this.nodesData);
this.simulation.force("link").links(this.linksData);
this.simulation.alphaDecay(0.05).alpha(1).restart();
}
我发现奇怪的是,在exit().remove()
之后,删除的节点保留在选择中。我尝试通过类似的操作来更新nodesRef
this.nodesRef = this.nodesRef.data(this.nodesData,d => d.id)
.enter()
./* defining nodes stuff*/
.merge(this.nodesRef);
但是它带给我同样的结果。我仍然认为我不正确地理解如何管理选择。
编辑:删除了古老的CodePen链接
答案 0 :(得分:1)
我终于有了工作!
This page对于理解选择非常有帮助。基本上,我一开始并不了解append()会返回一个新选择,而不仅仅是将内容添加到包含先前选择的变量中。
This page揭示了作者更新图形的方式。使用此模式使许多事情变得更简单。一般的想法是将节点拼接,弹出,推送,处理,并链接数据数组,然后以这种方式更新选择:
// Update the data, remove obsolete elements, add and merge new elements
nodesSelection = nodesSelection.data(nodesData, d => d.id);
nodesSelection.exit().remove();
nodesSelection = nodesSelection.enter()./* setup node shape*/.merge(nodesSelection);
// Repeat pattern for links
// ...
// Update simulation resources and "reheat" the graph
simulation.nodes(nodesData);
simulation.force("link",d3.forceLink(linksData).id( d => d.id));
simulation.alpha(1).restart();
我仍然需要弄清链接更新中的某些内容,Mike的示例仅通过执行simulation.force("link").links(links);
来更新模拟链接,但是到目前为止,这对我来说还不可行。可能与链接对象属性有关。
但这已经足够了,可以玩了:current Graph class here