D3 Examples

Richard Dalton

Force Chart

We can model relationships between entities using a Force Chart. Use SVG to draw the nodes and edges. The D3 Force layout provides a means of animating and interacting with the chart.

This example contains two data sets. 'People', which could be players in a game, and 'Killed' which captures the details of which players kill other players.


    //Width and height
    var w = 500;
    var h = 500;

    //Original data
    var dataset = {
        people: [
            { name: "Adam", r: 10 },
            { name: "Bob", r: 10 },
            { name: "Carrie", r: 10 },
            { name: "Donovan", r: 10 },
            { name: "Edward", r: 40 },
            { name: "Felicity", r: 25 },
            { name: "George", r: 15 },
            { name: "Hannah", r: 5 },
            { name: "Iris", r: 30 },
            { name: "Jerry", r: 20 }
        ],
        killed: [
            { source: 0, target: 1 },
            { source: 0, target: 2 },
            { source: 0, target: 3 },
            { source: 0, target: 4 },
            { source: 1, target: 5 },
            { source: 2, target: 5 },
            { source: 2, target: 5 },
            { source: 3, target: 4 },
            { source: 5, target: 8 },
            { source: 5, target: 9 },
            { source: 6, target: 7 },
            { source: 7, target: 8 },
            { source: 8, target: 9 }
        ]
    };

    // Initialize a default force layout,
    // using the nodes and edges in dataset
    var force = d3.layout.force()
        .nodes(dataset.people)
        .links(dataset.killed)
        .size([w, h])
        .linkDistance([200])
        .charge([-10])
        .start();

    var colors = d3.scale.category10();

    //Create SVG element
    var svg = d3.select("#draw_here")
        .append("svg")
        .attr("width", w)
        .attr("height", h);

    //Create edges as lines
    var lines = svg.selectAll("line")
        .data(dataset.killed)
        .enter()
        .append("line")
        .style("stroke", "#ccc")
        .style("stroke-width", 1);

    //Create nodes as circles
    var circles = svg.selectAll("circle")
        .data(dataset.people)
        .enter()
        .append("circle")
        .attr("r", function(d){
            return d.r;
        })
        .style("fill", function(d, i) {
            return colors(i);
        })
        .attr("opacity", "0.5")
        .call(force.drag);

    var text = svg.selectAll("text")
        .data(dataset.people)
        .enter()
        .append("text")
        .text(function (d) {
            return d.name;
        })
        .attr("text-anchor", "middle")
        .attr("font-family", "sans-serif")
        .attr("font-size", "11px");

    //Every time the simulation "ticks", this will be called
    force.on("tick", function() {
        lines.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; });

        circles.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });

        text.attr("x", function(d) { return d.x; })
            .attr("y", function(d) { return d.y; });
    });