Built with blockbuilder.org
forked from john-guerra's block: D3 Force Simulation
license: mit |
Built with blockbuilder.org
forked from john-guerra's block: D3 Force Simulation
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
</style> | |
</head> | |
<body> | |
<h1>Force Directed layout</h1> | |
<svg | |
width=800 | |
height=400 | |
id="network"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
// Copy drag from: https://bl.ocks.org/mbostock/4062045 | |
let svg = d3.select("#network"), | |
width = +svg.attr("width"), | |
height = + svg.attr("height"), | |
N = 100, | |
r = d3.scaleSqrt() | |
.domain([0, 100]) | |
.range([1, 15]); | |
let nodes = d3.range(N).map(() => { | |
return { | |
age: Math.random()*100, | |
}; | |
}); | |
let links = d3.range(N*3).map(() => { | |
return { | |
source:Math.floor(Math.random()*N), | |
target:Math.floor(Math.random()*N) | |
} | |
}); | |
console.log(width, height); | |
let simulation = d3.forceSimulation(nodes) | |
.force("center", d3.forceCenter(width/2, height/2)) | |
.force("charge", d3.forceManyBody().strength(-5)) | |
.force("collide", d3.forceCollide(16)) | |
.force("link", d3.forceLink(links) | |
.distance(50)) | |
.on("tick", ticked); | |
console.log("nodes", nodes); | |
console.log("links", links); | |
let sellinks = svg.selectAll(".link") | |
.data(links) | |
.enter() | |
.append("line") | |
.attr("class", "link") | |
.style("stroke", "#aaa") | |
.style("opacity", 0.9) | |
let selnodes = svg.selectAll(".node") | |
.data(nodes) | |
.enter() | |
.append("circle") | |
.attr("class", "node") | |
.style("fill", "steelblue") | |
.attr("r", 15) | |
function ticked() { | |
sellinks.attr("x1", (l) => l.source.x) | |
.attr("y1", (l) => l.source.y) | |
.attr("x2", (l) => l.target.x) | |
.attr("y2", (l) => l.target.y); | |
selnodes.attr("cx", (d) => d.x) | |
.attr("cy", (d) => d.y); | |
// console.log("ticked!"); | |
} | |
</script> | |
</body> |