Skip to content

Instantly share code, notes, and snippets.

Created September 23, 2017 09:48
Show Gist options
  • Save anonymous/b9ed4acc2b9a65c89819bddcb787c1c9 to your computer and use it in GitHub Desktop.
Save anonymous/b9ed4acc2b9a65c89819bddcb787c1c9 to your computer and use it in GitHub Desktop.
Basic Directional Force Layout Diagram
license: mit

This is an adaption of two of Mike Bostock's force layout examples (Mobile Patent Suits and Force-Directed Graph with Mouseover).

This particular graph is intended as a 'basic' example of a directional force layout graph (hence the arrows) and I intend to add additional examples with variations.

forked from d3noob's block: Basic Directional Force Layout Diagram

forked from anonymous's block: Basic Directional Force Layout Diagram

forked from anonymous's block: Basic Directional Force Layout Diagram

forked from anonymous's block: Basic Directional Force Layout Diagram

source target value
Harry Sally 1.2
Harry Mario 1.3
Sarah Alice 0.2
Eveie Alice 0.5
Peter Alice 1.6
Mario Alice 0.4
James Alice 0.6
Harry Carol 0.7
Harry Nicky 0.8
Bobby Frank 0.8
Alice Mario 0.7
Harry Lynne 0.5
Sarah James 1.9
Roger James 1.1
Maddy James 0.3
Sonny Roger 0.5
James Roger 1.5
Alice Peter 1.1
Johan Peter 1.6
Alice Eveie 0.5
Harry Eveie 0.1
Eveie Harry 2.0
Henry Mikey 0.4
Elric Mikey 0.6
James Sarah 1.5
Alice Sarah 0.6
James Maddy 0.5
Peter Johan 0.7
<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.js"></script>
<style>
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: #ccc;
stroke: #fff;
stroke-width: 1.5px;
}
text {
fill: #000;
font: 10px sans-serif;
pointer-events: none;
}
</style>
<body>
<script>
// get the data
d3.csv("force.csv", function(error, links) {
var nodes = {};
// Compute the distinct nodes from the links.
links.forEach(function(link) {
link.source = nodes[link.source] ||
(nodes[link.source] = {name: link.source, value: Math.random()});
link.target = nodes[link.target] ||
(nodes[link.target] = {name: link.target, value: Math.random()});
link.value = +link.value;
});
var width = 960,
height = 500;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(60)
.charge(-300)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// build the arrow.
svg.append("svg:defs").selectAll("path")
.data(["end"]) // Different link/path types can be defined here
.enter()
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
// .attr("class", function(d) { return "link " + d.type; })
.attr("class", "link")
.attr("marker-end", "url(#end)");
// define the nodes
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.call(force.drag);
// add the nodes
node.append("circle")
.attr("r", function(d) {
return d.value * 50;
});
// add the text
node.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
// add the curvy lines
function tick() {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" +
d.source.x + "," +
d.source.y + "A" +
dr + "," + dr + " 0 0,1 " +
d.target.x + "," +
d.target.y;
});
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment