Skip to content

Instantly share code, notes, and snippets.

@jowlo
Forked from heybignick/.block
Last active June 3, 2019 14:33
Show Gist options
  • Save jowlo/e474cbe633a24a84fa1e844a13b874bd to your computer and use it in GitHub Desktop.
Save jowlo/e474cbe633a24a84fa1e844a13b874bd to your computer and use it in GitHub Desktop.
D3.js v4 Force Directed Graph with Labels
license: gpl-3.0
height: 600

A quick adaptation of Mike Bostock's force-directed graph showing character co-occurence in Les Misérables. In this version, the character names are displayed. This is accomplished by wrapping both circles and text svg components within a group svg component.

Compare to the original diagram by Mike Bostock.

{
"nodes": [
{
"id": 0,
"start": 0,
"end": 66508,
"name": "(0, 66508)"
},
{
"id": 1,
"start": 66512,
"end": 66516,
"name": "(66512, 66516)"
},
{
"id": 2,
"start": 66676,
"end": 66712,
"name": "(66676, 66712)"
},
{
"id": 3,
"start": 66716,
"end": 66520,
"name": "(66716, 66520)"
},
{
"id": 4,
"start": 66524,
"end": 66556,
"name": "(66524, 66556)"
},
{
"id": 5,
"start": 66560,
"end": 66560,
"name": "(66560, 66560)"
},
{
"id": 6,
"start": 66564,
"end": 66736,
"name": "(66564, 66736)"
},
{
"id": 7,
"start": 66740,
"end": 66760,
"name": "(66740, 66760)"
},
{
"id": 8,
"start": 66764,
"end": 66768,
"name": "(66764, 66768)"
},
{
"id": 9,
"start": 66824,
"end": 66384,
"name": "(66824, 66384)"
},
{
"id": 10,
"start": 66388,
"end": 66424,
"name": "(66388, 66424)"
},
{
"id": 11,
"start": 66476,
"end": 65916,
"name": "(66476, 65916)"
},
{
"id": 12,
"start": 65960,
"end": 65796,
"name": "(65960, 65796)"
},
{
"id": 13,
"start": 65820,
"end": 66424,
"name": "(65820, 66424)"
},
{
"id": 14,
"start": 66428,
"end": 66018,
"name": "(66428, 66018)"
},
{
"id": 15,
"start": 65976,
"end": 66018,
"name": "(65976, 66018)"
},
{
"id": 16,
"start": 66022,
"end": 66094,
"name": "(66022, 66094)"
},
{
"id": 17,
"start": 66098,
"end": 66108,
"name": "(66098, 66108)"
},
{
"id": 18,
"start": 66134,
"end": 66142,
"name": "(66134, 66142)"
},
{
"id": 19,
"start": 66156,
"end": 66912,
"name": "(66156, 66912)"
},
{
"id": 20,
"start": 66916,
"end": 66932,
"name": "(66916, 66932)"
},
{
"id": 21,
"start": 66980,
"end": 66980,
"name": "(66980, 66980)"
},
{
"id": 22,
"start": 67004,
"end": 67016,
"name": "(67004, 67016)"
},
{
"id": 23,
"start": 67020,
"end": 67024,
"name": "(67020, 67024)"
},
{
"id": 24,
"start": 67028,
"end": 67044,
"name": "(67028, 67044)"
},
{
"id": 25,
"start": 67048,
"end": 66284,
"name": "(67048, 66284)"
},
{
"id": 26,
"start": 66308,
"end": 65828,
"name": "(66308, 65828)"
},
{
"id": 27,
"start": 65832,
"end": 65736,
"name": "(65832, 65736)"
},
{
"id": 28,
"start": 65760,
"end": 65860,
"name": "(65760, 65860)"
},
{
"id": 29,
"start": 65880,
"end": 66284,
"name": "(65880, 66284)"
},
{
"id": 30,
"start": 66288,
"end": 67056,
"name": "(66288, 67056)"
},
{
"id": 31,
"start": 67060,
"end": 67064,
"name": "(67060, 67064)"
},
{
"id": 32,
"start": 66992,
"end": 66932,
"name": "(66992, 66932)"
},
{
"id": 33,
"start": 66936,
"end": 66224,
"name": "(66936, 66224)"
},
{
"id": 34,
"start": 66232,
"end": 10000,
"name": "(66232, 10000)"
}
],
"links": [
{
"source": 0,
"target": 1
},
{
"source": 1,
"target": 2
},
{
"source": 2,
"target": 3
},
{
"source": 3,
"target": 4
},
{
"source": 4,
"target": 5
},
{
"source": 5,
"target": 6
},
{
"source": 6,
"target": 7
},
{
"source": 7,
"target": 8
},
{
"source": 8,
"target": 9
},
{
"source": 9,
"target": 10
},
{
"source": 10,
"target": 11
},
{
"source": 11,
"target": 12
},
{
"source": 12,
"target": 13
},
{
"source": 10,
"target": 14
},
{
"source": 14,
"target": 15
},
{
"source": 14,
"target": 15
},
{
"source": 14,
"target": 15
},
{
"source": 14,
"target": 15
},
{
"source": 14,
"target": 16
},
{
"source": 16,
"target": 17
},
{
"source": 17,
"target": 18
},
{
"source": 18,
"target": 19
},
{
"source": 19,
"target": 20
},
{
"source": 20,
"target": 21
},
{
"source": 21,
"target": 22
},
{
"source": 22,
"target": 23
},
{
"source": 23,
"target": 24
},
{
"source": 24,
"target": 25
},
{
"source": 25,
"target": 26
},
{
"source": 26,
"target": 27
},
{
"source": 27,
"target": 28
},
{
"source": 28,
"target": 29
},
{
"source": 25,
"target": 30
},
{
"source": 30,
"target": 31
},
{
"source": 31,
"target": 32
},
{
"source": 20,
"target": 33
},
{
"source": 33,
"target": 34
}
]
}
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.line::after {
content: '';
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 30px solid blue;
position: absolute;
right: -10px;
top: -15px;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
text {
font-family: sans-serif;
font-size: 10px;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var 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));
d3.json("cov.json", function(error, graph) {
if (error) throw error;
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("g")
.data(graph.nodes)
.enter().append("g")
var circles = node.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var lables = node.append("text")
.text(function(d) {
return d.name;
})
.attr('x', 6)
.attr('y', 3);
node.append("title")
.text(function(d) { return d.name; });
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.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; });
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
}
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment