This example demonstrates how to add and remove nodes and links from a force layout. The graph initially appears with three nodes A, B and C connected in a loop. Three seconds later, node B is removed, along with the links B-A and B-C. At six seconds, node B is reintroduced, restoring the original links B-A and B-C. This example uses the general update pattern for data joins.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .link { | |
| stroke: #000; | |
| stroke-width: 1.5px; | |
| } | |
| .node { | |
| fill: #000; | |
| stroke: #fff; | |
| stroke-width: 1.5px; | |
| } | |
| .node.a { fill: #1f77b4; } | |
| .node.b { fill: #ff7f0e; } | |
| .node.c { fill: #2ca02c; } | |
| </style> | |
| <body> | |
| <script src="//d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500; | |
| var color = d3.scale.category10(); | |
| var nodes = [], | |
| links = []; | |
| var force = d3.layout.force() | |
| .nodes(nodes) | |
| .links(links) | |
| .charge(-400) | |
| .linkDistance(120) | |
| .size([width, height]) | |
| .on("tick", tick); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height); | |
| var node = svg.selectAll(".node"), | |
| link = svg.selectAll(".link"); | |
| // 1. Add three nodes and three links. | |
| setTimeout(function() { | |
| var a = {id: "a"}, b = {id: "b"}, c = {id: "c"}; | |
| nodes.push(a, b, c); | |
| links.push({source: a, target: b}, {source: a, target: c}, {source: b, target: c}); | |
| start(); | |
| }, 0); | |
| // 2. Remove node B and associated links. | |
| setTimeout(function() { | |
| nodes.splice(1, 1); // remove b | |
| links.shift(); // remove a-b | |
| links.pop(); // remove b-c | |
| start(); | |
| }, 3000); | |
| // Add node B back. | |
| setTimeout(function() { | |
| var a = nodes[0], b = {id: "b"}, c = nodes[1]; | |
| nodes.push(b); | |
| links.push({source: a, target: b}, {source: b, target: c}); | |
| start(); | |
| }, 6000); | |
| function start() { | |
| link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; }); | |
| link.enter().insert("line", ".node").attr("class", "link"); | |
| link.exit().remove(); | |
| node = node.data(force.nodes(), function(d) { return d.id;}); | |
| node.enter().append("circle").attr("class", function(d) { return "node " + d.id; }).attr("r", 8); | |
| node.exit().remove(); | |
| force.start(); | |
| } | |
| function tick() { | |
| node.attr("cx", function(d) { return d.x; }) | |
| .attr("cy", function(d) { return d.y; }) | |
| 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; }); | |
| } | |
| </script> |
inactivist
commented
Feb 19, 2013
commented
Nov 10, 2015
can you give some description about start() method ? how ( and why ) dose it work ?
rdpoor
commented
Apr 19, 2016
I've just created a fork of this example, heavily commented, giving what I hope is a detailed explanation of the important concepts: https://gist.github.com/rdpoor/3a66b3e082ffeaeb5e6e79961192f7d8
(And I see that it appears in bl.ocks "by magic". Very nice!)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What is the purpose of the
var color = d3.scale.category10();at line 28? It appears to have no effect.