block by fil 1d045bf61b7184bafb3afd0b527473f6

Merge Sites

Full Screen

In answer to a question on the d3 Slack channel #help

See also the simpler version in one move

Built with blockbuilder.org

index.html

<!DOCTYPE html> 
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
  <script>
    // Feel free to change or delete any of the code you see in this editor!
    var svg = d3.select("body").append("svg")
      .attr("width", 960)
      .attr("height", 500)

    var data = d3.range(300).map(d => {
      return {
        x: 100 + 760 * Math.random(),
        y: 100 + 300 * Math.random(),
        w: 300 * Math.random(),
      }
    })

    function merge() {
      var merged = 0;
      data.forEach((d,i) => {
        if (d.w == 0) return;
        d.r = Math.sqrt(d.w);
        data.slice(0, i).forEach((e,j) => {
          if (e.w == 0) return;
          var dx = e.x - d.x,
              dy = e.y - d.y,
              dist2 = dx * dx + dy * dy,
              r2 = (d.r + e.r) * (d.r + e.r);
          if (dist2 < r2) {
            merged ++;
            if (d.w >= e.w) {
              d.x += dx * e.w / (d.w + e.w);
              d.y += dy * e.w / (d.w + e.w);
              d.w += e.w;
              e.w = 0;
            } else {
              e.x -= dx * d.w / (d.w + e.w);
              e.y -= dy * d.w / (d.w + e.w);
              e.w += d.w;
              d.w = 0;
            }
          }
        });
      });
      return merged;
    }
    
    function display(stop){
      circles.transition()
      .attr('r', d => Math.sqrt(d.w))
      .attr('cx', d => d.x)
      .attr('cy', d => d.y);
      circles.filter(d => !d.w)
        .attr('opacity', 0)
        .transition()
        .remove();
      if (!stop) setTimeout(function(){
      var merged = merge();
       if (merged) {
         console.log("merged", +merged);
         display();
       } else {
         console.log("ended");
         display("stop");
         circles
           .transition()
           .attr('opacity', 0.8);
       }
    }, 500);
    }
    
    var circles = svg.selectAll('circle')
    .data(data)
    .enter()
    .append('circle')
    .attr("fill", "#3498f7")
    .attr("opacity", 0.5);

    display(); 
    
    
  </script>
</body>