Creating network diagrams with D3.js

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;
}

10 thoughts on “Creating network diagrams with D3.js

  1. Permalink  ⋅ Reply

    João

    April 19, 2013 at 9:24am

    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

  2. Permalink  ⋅ Reply

    Jacob Briggs

    March 16, 2015 at 4:45pm

    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;
    }

    • Permalink  ⋅ Reply

      Rakesh Ranjan

      August 20, 2015 at 12:49pm

      How to make marker for arrow in script tag so that i can change its color(fill) dynamically

    • Permalink  ⋅ Reply

      Rithvika

      August 5, 2016 at 9:15am

      How to give images from json data?

  3. Permalink  ⋅ Reply

    Knut

    April 1, 2015 at 12:51pm

    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

  4. Permalink  ⋅ Reply

    Poyal Biswas

    April 14, 2015 at 3:14pm

    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?

  5. Permalink  ⋅ Reply

    Suyash

    June 26, 2015 at 7:35am

    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

  6. Permalink  ⋅ Reply

    Michael Kalango

    March 28, 2019 at 3:07pm

    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

Leave a Reply

Your email will not be published. Name and Email fields are required.