D3.js is a JavaScript library for manipulating documents based on data. It can be used for all sorts of visualizations including network diagrams. In this article we will create a network diagram with nodes and directed links between them, visualized by circles and lines with arrowheads. We start with the file index.html that holds the HTML and basic SVG structure:
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>Cloud</title> <script type="text/javascript" src="d3.v2.js"></script> </head> <body> <svg id="cloud" width="800" height="600"> <defs> <marker id="arrow" viewbox="0 -5 10 10" refX="18" refY="0" markerWidth="6" markerHeight="6" orient="auto"> <path d="M0,-5L10,0L0,5Z"> </marker> </defs> </svg> <link href="cloud.css" rel="stylesheet" type="text/css" /> <script src="cloud.js" type="text/javascript"></script> </body> </html>
The file cloud.js contains the Javascript code to generate the SVG code according to some JSON content:
var width = 1200; var height = 800; var color = d3.scale.category10(); var force = d3.layout.force() .charge(-180) .linkDistance(70) .size([width, height]); var svg = d3.select("#cloud"); d3.json("cloud.json", function(json) { force .nodes(json.nodes) .links(json.links) .start(); var links = svg.append("g").selectAll("line.link") .data(force.links()) .enter().append("line") .attr("class", "link") .attr("marker-end", "url(#arrow)"); var nodes = svg.selectAll("circle.node") .data(force.nodes()) .enter().append("circle") .attr("class", "node") .attr("r", 8) .style("fill", function(d) { return color(d.group); }) .call(force.drag); nodes.append("title") .text(function(d) { return d.name; }); force.on("tick", function() { links.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; }); nodes.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); });
The file cloud.json contains the JSON that the Javascript uses to create SVG:
{ "nodes": [ {"name":"Client 1", "group":1}, {"name":"Loadbalancer 1", "group":2}, {"name":"Webserver 1", "group":3}, {"name":"Webserver 2", "group":3} ], "links": [ {"source":0, "target":1, "value":1}, {"source":1, "target":2, "value":1}, {"source":1, "target":3, "value":1} ] }
The final file cloud.css contains the CSS to make things more pretty:
circle.node { stroke: #fff; stroke-width: 3px; } line.link { stroke-width: 2px; stroke: #999; stroke-opacity: 0.6; } marker#arrow { stroke: #999; fill: #999; }
Creating network diagrams with D3.js
Hi,
Awesome tutorial.. What if i want to add the name of the node to appear inside the node itself????
Thanks for the tutorial,
João
Joao, here you go:
cloud.js
var width = 1200;
var height = 800;
var color = d3.scale.category10();
var force = d3.layout.force()
.charge(-180)
.linkDistance(70)
.size([width, height]);
var svg = d3.select("#cloud");
d3.json("cloud.json", function(json) {
force
.nodes(json.nodes)
.links(json.links)
.start();
var links = svg.append("g").selectAll("line.link")
.data(force.links())
.enter().append("line")
.attr("class", "link")
.attr("marker-end", "url(#arrow)");
var nodes = svg.append("g").selectAll("circle.node")
.data(force.nodes())
.enter().append("circle")
.attr("class", "node")
.attr("r", 8)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
var texts = svg.append("g").selectAll("circle.node")
.data(force.nodes())
.enter().append("text")
.attr("class", "label")
.text(function(d) { return d.name; })
.call(force.drag);
force.on("tick", function() {
links.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; });
nodes.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
texts.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });
});
});
cloud.css
circle.node {
stroke: #fff;
stroke-width: 3px;
}
line.link {
stroke-width: 2px;
stroke: #999;
stroke-opacity: 0.6;
}
text.label {
font: 10px sans-serif;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
marker#arrow {
stroke: #999;
fill: #999;
}
How to make marker for arrow in script tag so that i can change its color(fill) dynamically
How to give images from json data?
Thanks a ton for this template!
I struggled for quite some time with the dragging behavior of the labels… :-/ But now it’s up and running.
Groetjes,
Knut
I am trying to develop a similar kind of project in eclipse. I just wanted to know the directory structure, as in where should the css files be located and where will my json data be kept?
hello
i want to display connection among nodes like a central node is connected to subnodes …i want to display it with sequence diagram..
can u please provide me one template to implement it
Hello,
Thanks for this great tutorial, very usefull to start great stuff with d3js.
I produced this jsfiddle example with your code :
http://jsfiddle.net/bilalel/7avxbpyj/
Bilal
Great Tutorial,
Hi Jan, I am trying to develop network diagram but unable display small and big nodes positions.
http://stackoverflow.com/questions/35377229/how-to-show-big-circle-outer-side-and-small-circle-inner-side-in-d3js
https://plnkr.co/edit/I9zhUBDgAct1b1zxEXI8?p=preview
Please Help Me.
Hi, how can i create such a project using a spreadsheet data to create the nodes, links and arrow direction dynamically. Would love the help as its all meant to be packaged as an app.
The generated network diagram can be interacted with to show the shortest links to things, a change in direction of arrow affects the spreadsheet data automatically