我想允许用户使用d3 forceSimulation或CoLa layout查看他们的网络,这意味着当用户触发事件时,我需要更改那些布局算法中正在更新的我的节点和边的x
和y
属性。
尤其是,这要求我能够停止仿真并阻止它们在我提供给它们的数据上更新那些属性,而另一个则处于“活动”状态-以及删除与它们关联的拖动处理程序。
我的渲染功能当前具有:
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);
}
一种解决方案可能是处理这些对象,例如delete d3_force['something_important']
更简单的方法可能会起作用,例如d3_force.nodes([])
等。
我不确定我将如何执行类似于拖动处理程序的操作,因为我对它们的工作方式不太了解。
为d3拖动处理程序(在d3v3中)建议的部分解决方案here:
var dragCallback = d3.select('rect#no-drag').property('__onmousedown.drag')['_'];
d3.select('rect#no-drag').on('mousedown.drag', null);
,然后稍后还原:
d3.selectAll('rect#no-drag').on('mousedown.drag', dragCallback);
答案 0 :(得分:2)
您需要做两件事:
如果模拟仍在运行,请停止该模拟,以防止其干扰您的节点坐标。可以通过调用d3_force.stop()
轻松完成此操作。不过,无需先检查它是否正在运行,因为在已经停止的仿真上调用它也不会造成伤害。
您以后可以通过调用d3_force.restart()
可能会抽回一些能量来加热它来重新激活仿真:d3_force.alpha(1).restart()
。
docs告诉我们如何摆脱拖动行为:
侦听器使用名称
.drag
,因此您可以按以下方式取消绑定拖动行为:selection.on(".drag", null);
在您的情况下,该值为node.on(".drag", null)
。如果用户切换回布局,则可以再次将拖动行为绑定到node
选择。为此,可能值得考虑先创建拖动行为,然后在以后重新绑定时绕过引用。