Built with blockbuilder.org
Last active
March 14, 2018 19:54
-
-
Save tomshanley/e4f17f5ddaed2f6282c31d44baa38da2 to your computer and use it in GitHub Desktop.
Force with links
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;top:0;right:0;bottom:0;left:0; } | |
line { stroke: black; stroke-width: 1px } | |
</style> | |
</head> | |
<body> | |
<script> | |
//have a play adding "actor" nodes, with unique names | |
var nodes = [ | |
{ "type": "actor", "name": "A", "value": 15 }, | |
{ "type": "actor", "name": "B", "value": 5 }, | |
//{ "type": "actor", "name": "C", "value": 25 }, | |
//{ "type": "actor", "name": "D", "value": 50 }, | |
{ "type": "event", "name": "event1", "value": 0 } | |
] | |
var links = [] | |
var w = 800, h = 800, r = 350 | |
const radians = 0.0174532925 | |
var totalActorValue = 0 | |
var inverseTotal = 0 | |
var numberOfActors = 0 | |
//total the actors' values | |
nodes.forEach(function(node){ | |
if (node.type == "actor") { | |
totalActorValue = totalActorValue + node.value | |
numberOfActors = numberOfActors + 1 | |
} | |
}) | |
//fix the circles to the radius | |
nodes.forEach(function(node, i){ | |
if (node.type == "actor") { | |
let a = (360/numberOfActors) * i | |
node.fx = w/2 + x(a, r) | |
node.fy = h/2 + y(a, r) | |
} | |
}) | |
//update the event total | |
nodes.forEach(function(node){ | |
node.value = node.type == "event" ? totalActorValue : node.value | |
}) | |
//set the link distances | |
nodes.forEach(function(node){ | |
node.valuePct = 1/(node.value/totalActorValue) | |
inverseTotal = node.type == "actor" ? inverseTotal + node.valuePct : inverseTotal | |
}) | |
nodes.forEach(function(node){ | |
node.inverseProportion = node.valuePct/inverseTotal | |
links.push({ "source": node.name, "target": "event1", "value": node.inverseProportion }) | |
}) | |
var g = d3.select("body").append("svg") | |
.attr("width", w) | |
.attr("height", h) | |
.append("g") | |
g.append("circle") | |
.attr("cx", w/2) | |
.attr("cy", h/2) | |
.attr("r", r) | |
.style("fill", "none") | |
.style("stroke", "grey") | |
var simulation = d3.forceSimulation() | |
.force("link", d3.forceLink().id(function(d) { return d.name; })) | |
var link = g.append("g") | |
.attr("class", "links") | |
.selectAll("line") | |
.data(links) | |
.enter() | |
.append("line"); | |
var node = g.append("g") | |
.attr("class", "nodes") | |
.selectAll("circle") | |
.data(nodes) | |
.enter() | |
.append("circle") | |
.attr("r", function(d){ | |
return d.value | |
}) | |
.style("fill", function(d){ | |
return d.type == "event" ? "PaleVioletRed" : "MediumSeaGreen" | |
}) | |
.style("stroke", "white") | |
.style("stroke-width", 3) | |
simulation | |
.nodes(nodes) | |
.on("tick", ticked) | |
simulation.force("link") | |
.links(links) | |
.distance(function(d){ | |
return d.value * (r*2) //- 50 //reduce the length to get 'tighter' 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("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }) | |
} | |
function x (angle, radius) { | |
// rotate 90 | |
let a = 90 - angle | |
return radius * Math.sin(a * radians) | |
} | |
function y (angle, radius) { | |
// rotate 90 | |
let a = 90 - angle | |
return radius * Math.cos(a * radians) | |
} | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment