问题
UPDATE : The graph now behaves correctly after removal of node(s). However, when I conditionally remove non-sequential nodes (e.g. 4,5,10) the graph does not display the correct nodes.
Please look at the updated click handler below (lots of debugging). I'm trying to remove all nodes with the "d.source" value == "news24", which are all the large blue circles. Although the array is correct after "removal", the incorrect nodes are being displayed. I suspect its something to do with node.exit(), but I'm not sure.
Full updated code : http://www.darkness.co.za/code/graph_test_2.zip
$('#btnRemove').click(function(e) {
// These are the large blue circles
var sourceToHide = "news24";
// DEBUG - Before Removal
for (i=0; i < nodes.length; i++) {
console.log("node_object[" + i + "].source = " + nodes[i].source);
console.log("-----------------------------------");
}
// Hold indices of items to remove
var itemsToRemove = [];
// Find items with the source to remove
for (i=0; i < nodes.length; i++) {
var nodeSource = nodes[i].source;
console.log("Node source = " + nodeSource + " sourceToHide = " + sourceToHide);
if (nodeSource == sourceToHide) {
itemsToRemove.push(i);
}
}
// Reverse removal array - makes splice work as expected
itemsToRemove.reverse();
// Remove items
for (i=0; i < itemsToRemove.length; i++) {
nodes.splice(itemsToRemove[i], 1);
}
// DEBUG - After Removal
for (i=0; i < nodes.length; i++) {
console.log("node_object[" + i + "].source = " + nodes[i].source);
console.log("-----------------------------------");
}
// Rebind the nodes to the array
node = svg.selectAll("circle")
.data(nodes)
// Remove the exit'ed node
node.exit().remove();
// Tell the layout that this is the new set of nodes
// so that it doesn't include the old one in the computation
force
.nodes(nodes)
// That's it. No need to restart the force layout
});
I've searched a lot, and tried many examples in isolation, but could not solve this issue for my particular setup and data.
Code :
Apologies, I had issues setting it up on JSFiddle (external files etc.) so you can get the full code here :
http://darkness.co.za/code/graph_test.zip
What I want to achieve:
(for this test) I want to remove a single node, and then redraw/restart the graph
What I've tried:
I've attempted to remove the last element from the Array of nodes, and then redraw the graph (circles and lines) and then call force.start()
The problem :
The node does disappear as desired, but the entire graph stops responding.
How do I correctly remove a node and then successfully restart the graph with it normal Drag behaviour ?
Note : I do at the end of the "drawGraph()" function call "force.start()"
Thanks
回答1:
You don't need to "restart" the graph in this case. All you should have to do is remove the node from the DOM and tell the force layout that there's a new set of nodes (same set as before MINUS the removed one). So, in the button's click handler:
// Button Listeners
$('#btnRemove').click(function(e) {
// Remove the node from the array
nodes.splice((nodes.length - 1), 1);
// Rebind the nodes to the array
node = svg.selectAll(".node")
.data(nodes)
// Remove the exit'ed node
node.exit().remove();
// Tell the layout that this is the new set of nodes
// so that it doesn't include the old one in the computation
force
.nodes(nodes)
// That's it. No need to restart the force layout
});
This doesn't address the removal of the node's link line, but you can follow the same approach to do that.
来源:https://stackoverflow.com/questions/25789097/d3-js-force-graph-doesnt-restart-layout-after-removing-node