首页 > 解决方案 > 我无法从 D3 力图中正确删除节点

问题描述

我正在开发一个基本的 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 链接

标签: javascriptd3.js

解决方案


我终于让它工作了!

这个页面对理解选择非常有帮助。基本上我一开始就不明白 append() 会返回一个新的选择,而不仅仅是向包含先前选择的变量添加东西。

这个页面揭示了作者更新图表的方式。使用这种模式可以让很多事情变得更简单。一般的想法是拼接、弹出、推送、对节点和链接数据数组进行处理,然后以这种方式更新选择:

// 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


推荐阅读