This example uses d3.forceCollide to prevent circles from overlapping.
forked from mbostock‘s block: Collision Detection
<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="800" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height,
tau = 2 * Math.PI;
var nodes = d3.range(1000).map(function(i) {
return {
r: Math.random() * 8 + 3
};
});
function neg(u){
return (-u + Math.abs(u))/2;
}
function shape(alpha){
for (var i = 0, n = nodes.length, node, k = alpha * 0.1; i < n; ++i) {
node = nodes[i];
var xa = node.x + 200,
xb = node.x - 200,
ya = node.y + 200,
yb = node.y - 200;
node.vx += (neg(xa) - neg(-xb));
node.vy += (neg(ya) - neg(-yb));
}
}
var simulation = d3.forceSimulation(nodes)
//.velocityDecay(0.2)
.force("shape", shape)
.force("collide", d3.forceCollide().radius(function(d) { return d.r + 0.5; }).iterations(2))
.on("tick", ticked);
var color = d3.scaleOrdinal(d3.schemeCategory10);
function ticked() {
context.clearRect(0, 0, width, height);
context.save();
context.translate(width / 2, height / 2);
nodes.forEach(function(d,i) {
context.beginPath();
context.moveTo(d.x + d.r, d.y);
context.arc(d.x, d.y, d.r, 0, tau);
context.fillStyle = color(i);
context.fill();
context.strokeStyle = "white";
context.stroke();
});
context.restore();
}
</script>