我无法从D3力图中正确删除节点

时间:2019-02-08 19:06:01

标签: javascript d3.js

我正在研究基本的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链接

1 个答案:

答案 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