如何在 fabricjs 中添加没有重叠的随机圆 canvas

how to add random circles with no overlap inside a fabricjs canvas

我正在尝试提出一种算法,在 fabricj canvas; 中添加 没有重叠的随机圆 下面的片段是我试过的。

const canvas = new fabric.Canvas('gameCanvas', {selection: false});
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
let rectangle;

document.addEventListener('DOMContentLoaded', function(){
    rectangle = new fabric.Rect({
                    width: 250,
                    height: 100,
                    fill: 'blue',
                    opacity: 0.2,
                    left: 200,
                    top: 140
      });
      canvas.add(rectangle);
});

document.getElementById('addCirclesBtn').addEventListener('click', function(){
    drawCircles();
});

function drawCircles()
{
   for(let i = 1; i <=20; i++)
   {
       let x= Math.random() * (rectangle.width - rectangle.left) + rectangle.left;
       let y = Math.random() * (rectangle.height - rectangle.top) + rectangle.top;
       let circle =  new fabric.Circle({
            left: x,
            top: y,
            strokeWidth: 2,
            radius: 10,
            fill: 'white',
            stroke: '#666',
            selectable: false,
            hoverCursor: 'default',
            hasControls: false,
            hasBorders: false
      });
      
      canvas.add(circle);
   }
   
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.min.js"></script>
<canvas id="gameCanvas" width="500" height="300" style="border: 2px solid green;"></canvas>
<button id="addCirclesBtn">ADD CIRCLES</button>

这是我想出的,主要逻辑在函数 drawCircles() 中,在添加到矩形内之前检查圆是否重叠。需要注意的是程序在矩形内添加了100个圆圈

const canvas = new fabric.Canvas('gameCanvas', {selection: false});
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
let rectangle;
const radius = 10;
let min_x;
let min_y;
let max_x;
let max_y;
let circles;

document.addEventListener('DOMContentLoaded', function(){
    drawRectangle();
    min_x = rectangle.left - rectangle.width / 2 ;
    //min_x = 250 - 200/2;
    max_x = rectangle.left + rectangle.width / 2;
    //max_x = 250 + 200/2;
    
    min_y = rectangle.top - rectangle.height / 2 ;
    //min_y = 150 - 100/2;
    max_y = rectangle.top + rectangle.height / 2;
    //max_y = 150 + 100/2;
});

function drawRectangle()
{
    rectangle = new fabric.Rect({
                    width: 200,
                    height: 100,
                    fill: 'blue',
                    opacity: 0.2,
                    left: 250,
                    top: 150
      });
      
      canvas.add(rectangle);
}

document.getElementById('addCirclesBtn').addEventListener('click', function(){
    canvas.clear();
    circles = [];
    drawRectangle();
    drawCircles();
});

function drawCircles()
{
   let anti_crash_count = 0
   while(circles.length < 100)
   {
       let circle =  new fabric.Circle({
            left: getRandomNumber(min_x + radius, max_x - radius),
            top: getRandomNumber(min_y + radius, max_y  - radius),
            strokeWidth: 2,
            radius: radius,
            fill: 'white',
            stroke: '#666',
            selectable: false,
            hoverCursor: 'default',
            hasControls: false,
            hasBorders: false,
            originX:'center',
            originY:'center'
       });
       
       let isOverlapping = false;
       
       for(let j = 0; j < circles.length; j++)
       {
          let previous_circle = circles[j];
          let distance = Math.hypot(circle.left - previous_circle.left, circle.top - previous_circle.top);
          
          if(distance < (circle.radius + previous_circle.radius))
          {
              isOverlapping = true;
              break;
          }
       }
       
       if(!isOverlapping)
       {
          canvas.add(circle);
          circles.push(circle);
       }
       anti_crash_count ++;
       if(anti_crash_count > 1000)
       {
          break;
       }
   }
}


function getRandomNumber(min, max)
{
    return Math.floor((Math.random() * (max - min)) + min);

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.min.js"></script>
<canvas id="gameCanvas" width="500" height="300" style="border: 2px solid green;"></canvas>
<button id="addCirclesBtn">ADD CIRCLES</button>

如果有任何关于如何改进它的想法,我将不胜感激。