Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.grid {
stroke: #9A8B7A;
stroke-width: 1px;
fill: #ce1c28;
}
.link {
stroke: #597761;
fill: none;
}
.node { 1
fill: #EBD8C1;
stroke: #9A8B7A;
stroke-width: 1px;
}
circle.active {
fill: #FE9922;
}
path.active {
stroke: #FE9922;
}
circle.source {
fill: #93C464;
}
circle.target {
fill: #41A368;
}
</style>
</head>
<body>
<script>
// Feel free to change or delete any of the code you see in this editor!
var 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])
})
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500)
function createForceLayout(nodes,edges) {
var roleScale = d3.scaleOrdinal()
.domain(["contractor", "employee", "manager"])
.range(["#75739F", "#41A368", "#FE9922"])
var nodeHash = nodes.reduce((hash, node) => {hash[node.id] = node;
return hash;
}, {})
edges.forEach(edge => {
edge.weight = parseInt(edge.weight)
edge.source = nodeHash[edge.source]
edge.target = nodeHash[edge.target]
})
var linkForce = d3.forceLink()
var simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(-40))
.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);
var 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);
nodes.forEach(d => {
d.degreeCentrality = edges.filter(
p => p.source === d || p.target === d).length
})
var marker = d3.select("svg").append('defs')
.append('marker')
.attr("id", "triangle")
.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(#triangle)");
d3.select("#controls").append("button")
.on("click", sizeByDegree).html("Degree Size")
function sizeByDegree() {
simulation.stop()
simulation.force("charge", d3.forceManyBody()
.strength(d => -d.degreeCentrality * 20))
simulation.restart()
d3.selectAll("circle")
.attr("r", d => d.degreeCentrality * 2)
}
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})`)
}
}
function filterNetwork() {
simulation.stop()
var originalNodes = simulation.nodes()
var originalLinks = simulation.force("link").links()
var influentialNodes = originalNodes.filter(d => d.role === "employee")
var influentialLinks = originalLinks.filter(d =>
influentialNodes.includes(d.source) &&
influentialNodes.includes(d.target))
d3.selectAll("g.node")
.data(influentialNodes, d => d.id)
.exit()
.transition()
.duration(4000)
.style("opacity", 0)
.remove()
d3.selectAll("line.link")
.data(influentialLinks, d => `${d.source.id}-${d.target.id}`)
.exit()
.transition()
.duration(3000)
.style("opacity", 0)
.remove()
simulation
.nodes(influentialNodes)
simulation.force("link")
.links(influentialLinks)
simulation.alpha(0.1)
simulation.restart()
}
</script>
</body>
https://d3js.org/d3.v4.min.js