I want to allow users to view their network using either a d3 forceSimulation or a CoLa layout, which means when a user fires an event, I need to change out which of those layout algorithms is updating the x
and y
attributes of my nodes and edges.
In particular, this requires that I be able to stop the simulations and prevent them from updating those attributes on the data I give them while the other is "active" -- as well as removing the drag handlers associated with them.
My render function currently has:
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);
}
One solution might be to mangle these objects, e.g. delete d3_force['something_important']
Something simpler might work, like d3_force.nodes([])
or somesuch.
I'm not sure how I would do something similar to the drag handlers because I'm less familiar with how those work.
Update 1:
A partial solution suggested for the d3 drag handler (in d3v3) here:
var dragCallback = d3.select('rect#no-drag').property('__onmousedown.drag')['_'];
d3.select('rect#no-drag').on('mousedown.drag', null);
and then restoring it later:
d3.selectAll('rect#no-drag').on('mousedown.drag', dragCallback);