Force-Directed Graph
Layout algorithm inspired by Tim Dwyer and Thomas Jakobsen. Data based on character coappearence in Victor Hugo’s Les Misérables, compiled by Donald Knuth.
Source Code
1 var w = 960,
2 h = 500,
3 fill = d3.scale.category20();
4
5 var vis = d3.select("#chart")
6 .append("svg:svg")
7 .attr("width", w)
8 .attr("height", h);
9
10 d3.json("miserables.json", function(json) {
11 var force = d3.layout.force()
12 .charge(-120)
13 .linkDistance(30)
14 .nodes(json.nodes)
15 .links(json.links)
16 .size([w, h])
17 .start();
18
19 var link = vis.selectAll("line.link")
20 .data(json.links)
21 .enter().append("svg:line")
22 .attr("class", "link")
23 .style("stroke-width", function(d) { return Math.sqrt(d.value); })
24 .attr("x1", function(d) { return d.source.x; })
25 .attr("y1", function(d) { return d.source.y; })
26 .attr("x2", function(d) { return d.target.x; })
27 .attr("y2", function(d) { return d.target.y; });
28
29 var node = vis.selectAll("circle.node")
30 .data(json.nodes)
31 .enter().append("svg:circle")
32 .attr("class", "node")
33 .attr("cx", function(d) { return d.x; })
34 .attr("cy", function(d) { return d.y; })
35 .attr("r", 5)
36 .style("fill", function(d) { return fill(d.group); })
37 .call(force.drag);
38
39 node.append("svg:title")
40 .text(function(d) { return d.name; });
41
42 vis.style("opacity", 1e-6)
43 .transition()
44 .duration(1000)
45 .style("opacity", 1);
46
47 force.on("tick", function() {
48 link.attr("x1", function(d) { return d.source.x; })
49 .attr("y1", function(d) { return d.source.y; })
50 .attr("x2", function(d) { return d.target.x; })
51 .attr("y2", function(d) { return d.target.y; });
52
53 node.attr("cx", function(d) { return d.x; })
54 .attr("cy", function(d) { return d.y; });
55 });
56 });