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 | |