Skip to content

Instantly share code, notes, and snippets.

@jwilber
Last active August 22, 2018 05:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwilber/546b424b30126524dec2ee4a134b7c82 to your computer and use it in GitHub Desktop.
Save jwilber/546b424b30126524dec2ee4a134b7c82 to your computer and use it in GitHub Desktop.
force-directed network diagram
license: mit
source target weight
Jim Irene 5
Susie Irene 5
Jim Susie 5
Susie Kai 5
Shirley Kai 5
Shelby Kai 5
Kai Susie 5
Kai Shirley 5
Kai Shelby 5
Erik Zan 5
Tony Zan 5
Tony Fil 5
Tony Ian 5
Tony Adam 5
Fil Tony 4
Ian Miles 1
Adam Tony 3
Miles Ian 2
Miles Ian 3
Erik Kai 2
Erik Nadieh 2
Jim Nadieh 2
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js" type="text/JavaScript"></script>
<style>
.node {
fill: #4F442B;
}
.link {
stroke: #93C464;
}
</style>
</head>
<body>
<div id="viz">
<svg style="width:600px;height:600px;" ></svg>
</div>
<script>
const roleScale = d3.scaleOrdinal()
.domain(["contractor", "employee", "manager"])
.range(["#75739F", "#41A368", "#FE9922"]);
const PromiseWrapper = d => new Promise(resolve => d3.csv(d, p => resolve(p)));
Promise
.all([
PromiseWrapper("nodelist.csv"),
PromiseWrapper("edgelist.csv")
])
.then(resolve => {
createForceLayout(resolve[0], resolve[1]);
});
function createForceLayout(nodes,edges) {
let nodeHash = {};
nodes.forEach(node => {
nodeHash[node.id] = node;
});
edges.forEach(edge => {
edge.weight = parseInt(edge.weight);
edge.source = nodeHash[edge.source];
edge.target = nodeHash[edge.target];
});
let linkForce = d3.forceLink();
let simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(-35))
.force("center", d3.forceCenter().x(300).y(300))
.force("link", linkForce)
.nodes(nodes)
.on("tick", forceTick);
simulation.force("link").links(edges);
d3.select("svg").selectAll("line.link")
.data(edges, d => `${d.source.id}-${d.target.id}`)
.enter()
.append("line")
.attr("class", "link")
.style("opacity", .5)
.style("stroke-width", d => d.weight);
let nodeEnter = d3.select("svg").selectAll("g.node")
.data(nodes, d => d.id)
.enter()
.append("g")
.attr("class", "node");
nodeEnter.append("circle")
.attr("r", 5)
.style("fill", d => roleScale(d.role));
nodeEnter.append("text")
.style("text-anchor", "middle")
.attr("y", 15)
.text(d => d.id);
function forceTick() {
d3.selectAll("line.link")
.attr("x1", d => d.source.x)
.attr("x2", d => d.target.x)
.attr("y1", d => d.source.y)
.attr("y2", d => d.target.y);
d3.selectAll("g.node")
.attr("transform", d => `translate(${d.x},${d.y})`);
}
let marker = d3.select('svg').append('defs')
.append('marker')
.attr('id', 'tri')
.attr('refX', 12)
.attr('refY', 6)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12)
.attr('markerHeight', 18)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 0 12 6 0 12 3 6');
d3.selectAll('line').attr('marker-end', "url(#tri)");
}
</script>
</body>
</html>
id role salary
Irene manager 300000
Zan manager 380000
Jim employee 150000
Susie employee 90000
Kai employee 135000
Shirley employee 60000
Erik employee 90000
Shelby employee 150000
Tony employee 72000
Fil employee 35000
Adam employee 85000
Ian employee 83000
Miles employee 99000
Sarah employee 160000
Nadieh contractor 240000
Hajra contractor 280000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment