D3js V4: Add Nodes To Force-directed Graph
I would like to render a force-directed graph in d3js v4 and provide a function for dynamically adding new nodes and links to the simulation. My first attempt (see below) still has
Solution 1:
You forgot to merge() your nodes. I have updated your code quickly:
graph.js
varGraph = function(targetElement, graph) {
var self = this,
width = targetElement.offsetWidth,
height = width / 2,
svg = d3.select(targetElement).append('svg')
.attr("width", width)
.attr("height", height),
simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2)),
linkGroup = svg.append("g")
.attr("class", "links"),
nodeGroup = svg.append("g")
.attr("class", "nodes"),
update = function() {
// Redefine and restart simulation
simulation.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
// Update links
link = linkGroup
.selectAll("line")
.data(graph.links);
// Enter links
linkEnter = link
.enter().append("line");
link = linkEnter
.merge(link);
// Exit any old links
link.exit().remove();
// Update the nodes
node = nodeGroup.selectAll("circle").data(graph.nodes);
// Enter any new nodes
nodeEnter = node.enter().append("circle")
.attr("r", 5)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node = nodeEnter.merge(node);
// Exit any old nodes
node.exit().remove();
functionticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
},
dragstarted = function(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
},
dragged = function(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
},
dragended = function(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
},
expandGraph = function(links, nodes) {
for (var i=0; i < nodes.length; i++) {
console.log('adding node', nodes[i]);
graph.nodes.push(nodes[i]);
}
for (var i=0; i < links.length; i++) {
console.log('adding link', links[i]);
graph.links.push(links[i]);
}
update();
};
// Public functionsthis.expandGraph = expandGraph;
update();
};
Actually I don't understand this new function 100%, but you always need to merge your new links and nodes (i.e. linkEnter and nodeEnter) with your existing graph. If you don't do this, your old Graph kind of dies...
Mike Bostock made an example how to use merge here:
https://bl.ocks.org/mbostock/3808218
Post a Comment for "D3js V4: Add Nodes To Force-directed Graph"