block by fil 07f00f90524c4c2b99c944780c2f4e7c

Force move 400 dots in 10 buildings

Full Screen

This example uses d3.forceCollide to prevent circles from overlapping.

forked from mbostock‘s block: Collision Detection

See also Bounded Force Layout - very tightly packed.

forked from Fil‘s block: Collision Detection in a tight square

index.html

<!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 buildings = d3.range(10).map(function(i) {
  return {
    x: (-0.5 + Math.random()) * width * 0.8,
    y: (-0.5 + Math.random()) * height * 0.8,
  };
});

var nodes = d3.range(400).map(function(i) {
  return {
    r: Math.random() * 8 + 3,
    building: Math.floor(Math.random() * buildings.length)
  };
});

  
  function shape(alpha){
   for (var i = 0, n = nodes.length, node, k = alpha * 0.1; i < n; ++i) {
    node = nodes[i];
     var dx = node.x - buildings[node.building].x,
         dy = node.y - buildings[node.building].y;
     node.vx -= dx * k;
     node.vy -= dy * k;
   }
  }
  
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(d.building);
    context.fill();
    context.strokeStyle = "white";
    context.stroke();
  });
  
  context.restore();
}

</script>