This example uses d3.forceCollide to prevent circles from overlapping.
forked from mbostock's block: Collision Detection
license: gpl-3.0 | |
height: 960 |
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> |
�PNG | |