d3 collapsible force layout

by Douglas Duhaime

HTML

<script src="https://d3js.org/d3.v4.0.0-alpha.50.min.js"></script>

CSS

line {
  stroke: #666;
}

.node {
  pointer-events: all;
}

circle {
  stroke: none;
  stroke-width: 40px;
}

.node text {
  font: 8px sans-serif;
}

JavaScript

var width = 960,
    height = 600;

var root = {
	"name": "server1900",
	"children": [{
		"name": "server913",
		"_children": null,
		"children": [{
			"name": "server948"
		}, {
			"name": "server946"
		}]
	}, {
		"name": "server912",
		"_children": null,
		"children": [{
			"name": "server984"
		}, {
			"name": "server983"
		}]
	}, {
		"name": "server911",
		"_children": null,
		"children": [{
			"name": "server999",
			"_children": null,
			"children": [{
				"name": "server992"
			}]
		}]
	}]
};

//initialising hierarchical data
root = d3.hierarchy(root);

var i = 0;

var transform = d3.zoomIdentity;;

var nodeSvg, linkSvg, simulation, nodeEnter, linkEnter ;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(d3.zoom().scaleExtent([1 / 2, 8]).on("zoom", zoomed))
  .append("g")
    .attr("transform", "translate(40,0)");

function zoomed() {
  svg.attr("transform", d3.event.transform);
}

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))
  .on("tick", ticked);

update();

function update() {
  var nodes = flatten(root);
  var links = root.links();

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

  linkSvg.exit().remove();

  var linkEnter = linkSvg.enter()
      .append("line")
      .attr("class", "link");
	
  linkSvg = linkEnter.merge(linkSvg)
  
  nodeSvg = svg.selectAll(".node")
    .data(nodes, function(d) { return d.id; })

  nodeSvg.exit().remove();

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

    nodeEnter.append("circle")
      .attr("r", 4  )
      .append("title")
        .text(function(d) { return d.data.name; })

   ...