d3 v4 force

by b_g_v

HTML

<script src="https://d3js.org/d3.v4.js"></script>
<svg width="960" height="600"></svg>

CSS

.link {
  stroke: #aaa;
}

.node {
  pointer-events: all;
  stroke: none;
  stroke-width: 40px;
}

JavaScript

var nodes = [
  {"id": 1, "name": "server 1"},
  {"id": 2, "name": "server 2"},
  {"id": 3, "name": "server 3"},
  {"id": 4, "name": "server 4"},
  {"id": 5, "name": "server 5"},
  {"id": 6, "name": "server 6"},
  {"id": 7, "name": "server 7"},
  {"id": 8, "name": "server 8"},
  {"id": 9, "name": "server 9"}
]

var links = [
  {source: 1, target: 2},
  {source: 1, target: 3},
  {source: 1, target: 4},
  {source: 2, target: 5},
  {source: 2, target: 6},
  {source: 3, target: 7},
  {source: 5, target: 8},
  {source: 6, target: 9},
]

var index = 10;
var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    node,
    link;

var 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));

update();

function update() {
  link = svg.selectAll(".link")
    .data(links, function(d) { return d.target.id; })

  link = link.enter()
    .append("line")
    .attr("class", "link");

  node = svg.selectAll(".node")
    .data(nodes, function(d) { return d.id; })

  node = node.enter()
    .append("g")
    .attr("class", "node")
    .on("click", click)
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));

  node.append("circle")
    .attr("r", 2.5)

  node.append("title")
      .text(function(d) { return d.id; });

  node.append("text")
      .attr("dy", 3)
      .text(function(d) { return d.name; });

  simulation
      .nodes(nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(links);
}

function click(d) {
  nodes.push({id: index, name: "server " + index});
  links.push({source: d.id, target: index});
  index++;
  update();
}

function ticked() {
  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;...