如何完全删除 d3 forceSimulation 及其拖动处理程序

Ale*_*ail 3 javascript d3.js webcola

我希望允许用户使用d3 forceSimulationCoLa 布局查看他们的网络,这意味着当用户触发事件时,我需要更改哪些布局算法正在更新我的节点和边的属性xy

特别是,这要求我能够停止模拟并防止它们在其他属性处于“活动”状态时更新我提供给它们的数据上的这些属性,以及删除与它们关联的拖动处理程序。

我的渲染函数目前有:

if (use_cola) {

  // MUST TURN OFF D3 AND ITS DRAG HANDLERS!

  force = cola_force.nodes(graph.nodes)
    .links(links)
    .groups(groups[group_nodes_by])
    .jaccardLinkLengths(repulsion_strength, 0.7)
    .avoidOverlaps(true)
    .start(50, 0, 50);

  node.call(cola_force.drag);
  group.call(cola_force.drag);

  cola_force.on('tick', ticked);

} else {  // d3

  // MUST TURN OFF COLA AND ITS DRAG HANDLERS!

  force = d3_force.nodes(graph.nodes)
    .force("link", d3.forceLink(links))
    .force("charge", d3.forceManyBody().strength(-repulsion_strength))
    .force("center", d3.forceCenter(w / 2, h / 2));

  node.call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended));  // where those are the conventional functions

  d3_force.on('tick', ticked);
}
Run Code Online (Sandbox Code Playgroud)

一种解决方案可能是破坏这些对象,例如delete d3_force['something_important']

一些更简单的东西可能会起作用,比如d3_force.nodes([])之类的。

我不确定如何做与拖动处理程序类似的事情,因为我不太熟悉它们的工作原理。

更新1:

此处为 d3 拖动处理程序(在 d3v3 中)建议的部分解决方案:

var dragCallback = d3.select('rect#no-drag').property('__onmousedown.drag')['_'];

d3.select('rect#no-drag').on('mousedown.drag', null);
Run Code Online (Sandbox Code Playgroud)

然后稍后恢复:

d3.selectAll('rect#no-drag').on('mousedown.drag', dragCallback);
Run Code Online (Sandbox Code Playgroud)

alt*_*lus 6

你需要做两件事:

  1. 如果模拟仍在运行,请停止模拟,以防止它扰乱节点坐标。这可以通过调用轻松完成d3_force.stop()。不过,无需首先检查它是否正在运行,因为在已经停止的模拟上调用它也不会造成伤害。

    d3_force.restart()您稍后可以通过调用可能泵入一些能量来加热它来重新激活模拟: d3_force.alpha(1).restart()

  2. 文档告诉我们如何摆脱拖动行为

    侦听器使用名称.drag,因此您可以随后取消绑定拖动行为,如下所示:

     selection.on(".drag", null);
    
    Run Code Online (Sandbox Code Playgroud)

    在你的情况下,这将是node.on(".drag", null). 如果用户切换回布局,您可以再次将拖动行为绑定到选择node。为此,可能值得考虑预先创建拖动行为,并在稍后重新绑定时传递引用。