|
<!DOCTYPE html> |
|
<svg width="960" height="500"></svg> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
|
|
var svg = d3.select("svg"), |
|
width = +svg.attr("width"), |
|
height = +svg.attr("height"), |
|
g = svg.append("g"); |
|
|
|
var radius = 4.5; |
|
|
|
var n = 100, |
|
nodes = d3.range(n).map(function(i) { return {index: i}; }), |
|
links = d3.range(n).map(function(i) { return {source: i, target: i + 1}; }); |
|
|
|
links.pop(); |
|
|
|
var simulation = d3.forceSimulation(nodes) |
|
.force("charge", d3.forceManyBody().strength(-180)) |
|
.force("link", d3.forceLink(links).strength(1).iterations(10)) |
|
.force('center', d3.forceCenter(width / 2, height / 2)) |
|
.force("collide", d3.forceCollide((d,i) => (Math.random() * (radius + 2)))) |
|
.force("x", d3.forceX(width / 2)) |
|
.force("y", d3.forceY()) |
|
.stop(); |
|
|
|
var loading = svg.append("text") |
|
.attr("dy", "0.35em") |
|
.attr("text-anchor", "middle") |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", 10) |
|
.text("Simulating. One moment please…"); |
|
|
|
// Use a timeout to allow the rest of the page to load first. |
|
d3.timeout(function() { |
|
loading.remove(); |
|
|
|
// See https://github.com/d3/d3-force/blob/master/README.md#simulation_tick |
|
for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) { |
|
simulation.tick(); |
|
} |
|
|
|
g.append("g") |
|
.attr("stroke", "#000") |
|
.attr("stroke-width", 1.5) |
|
.selectAll("line") |
|
.data(links) |
|
.enter().append("line") |
|
.attr("x1", function(d) { return d.source.x = Math.max(radius, Math.min(width - radius, d.source.x)); }) |
|
.attr("y1", function(d) { return d.source.y = Math.max(radius, Math.min(height - radius, d.source.y)); }) |
|
.attr("x2", function(d) { return d.target.x = Math.max(radius, Math.min(width - radius, d.target.x)); }) |
|
.attr("y2", function(d) { return d.target.y = Math.max(radius, Math.min(height - radius, d.target.y)); }); |
|
|
|
g.append("g") |
|
.attr("stroke", "#fff") |
|
.attr("stroke-width", 1.5) |
|
.selectAll("circle") |
|
.data(nodes) |
|
.enter().append("circle") |
|
.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); }) |
|
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); }) |
|
.attr("r", 4.5); |
|
}); |
|
|
|
</script> |