reactjs 生成无重叠的随机div

llew8vvj  于 2022-12-26  发布在  React
关注(0)|答案(1)|浏览(238)

我尝试使用TypeScript和React创建一个简单的项目,以便能够生成一个新的<div>,它具有随机的宽度和高度(最小值/最大值50/300 px),并随机放置在一个 Package 器中(在本例中为1920 x1080)。
目标是检查新生成的div矩形是否与现有div重叠。
如果没有,创建元素,否则生成新的位置和大小并再次检查,目标是尽可能多地填充 Package 器,因为div的最小/最大大小已经设置,并且没有重叠。
到目前为止,我设法编写了生成随机位置和大小的代码,但我在检查冲突和在没有空闲空间时发送消息方面遇到了麻烦。

const [count,setCount]=useState(0)
  const wrapper = document.getElementById('wrapper');
  var posX:number,posY:number,divSizeH:number,divSizeW:number;
  var willOverlap:boolean=false;
  function createRandomRectangle(){
    divSizeW = Math.round(((Math.random()*250) + 50));
    divSizeH = Math.round(((Math.random()*250) + 50));
    if (wrapper!=null) {
      const width = wrapper.offsetWidth , height = wrapper.offsetHeight;
      posX = Math.round( (Math.random() * ( width - divSizeW )) );
      posY = Math.round( (Math.random() * ( height - divSizeH )) );
       //checking collision
    document.querySelectorAll('.Rectangle').forEach(element=>{
          var r2 = element.getBoundingClientRect();
   //my attempt       //if(((posX>=r2.x&&posX<=r2.right)&&(posY>=r2.top&&posY<=r2.bottom))||((posX+divSizeW>=r2.x&&posX+divSizeW<=r2.right)&&(posY>=r2.top&&posY<=r2.bottom))||((posX>=r2.x&&posX<=r2.right)&&(posY+divSizeH>=r2.top//&&posY+divSizeH<=r2.bottom))||((posX+divSizeW>=r2.x&&posX+divSizeW<=r2.right)&&(posY+divSizeH>=r2.top&&posY+divSizeH<=r2.bottom))){
        //copied from someone elses code for checking collisions
            if((posX <= r2.x && r2.x <= posX+divSizeW) && (posY <= r2.y && r2.y <= posY+divSizeH) ||
            (posX <= r2.x && r2.x <= posX+divSizeW) && (posY <= r2.bottom && r2.bottom <= posY+divSizeH) ||
            (posX <= r2.x+r2.height && r2.x+r2.height <= posX+divSizeW) && (posY <= r2.y+r2.width && r2.y+r2.width <= posY+divSizeW) ||
            (posX <= r2.x+r2.height && r2.x+r2.height <= posX+divSizeW) && (posY <= r2.y && r2.y <= posY+divSizeW)){
            willOverlap=true;
            while(willOverlap){
              posX = Math.round((Math.random() * ( width- divSizeW)));
              posY = Math.round((Math.random() * (  height- divSizeH)));
              divSizeW = Math.round(((Math.random()*250) + 50));
              divSizeH = Math.round(((Math.random()*250) + 50));
              if(!(((posX>=r2.x&&posX<=r2.right)&&(posY>=r2.top&&posY<=r2.bottom))||((posX+divSizeW>=r2.x&&posX+divSizeW<=r2.right)&&(posY>=r2.top&&posY<=r2.bottom))||((posX>=r2.x&&posX<=r2.right)&&(posY+divSizeH>=r2.top&&posY+divSizeH<=r2.bottom))||((posX+divSizeW>=r2.x&&posX+divSizeW<=r2.right)&&(posY+divSizeH>=r2.top&&posY+divSizeH<=r2.bottom)))){
                willOverlap=false;
              }
            }
          }
        })
    }
      

    }
    //if there is no more place send message and dont create....
      const newDiv = document.createElement('div');
      newDiv.classList.add('Rectangle');
      newDiv.style.width=divSizeW+"px";
      newDiv.style.height=divSizeH+"px";
      newDiv.style.left=posX+"px";
      newDiv.style.top=posY+"px";
      boxxy?.appendChild(newDiv);
      setCount(count+1);
    
      
  }
xqkwcwgp

xqkwcwgp1#

正如你开始猜测的那样,你需要重复你的代码(这里是新的位置和大小+检查碰撞),以防你发现碰撞。
但是,由于您在forEach循环中对已有的矩形列表执行了重复操作,因此新生成的位置和大小不会与之前的矩形(列表的开头)进行重新检查,因此您可能会遇到冲突元素。
另一个问题,更困难的是,检测你的 Package 器什么时候是“满的”,或者更确切地说,当空白的空间不能再容纳任何新的矩形,给定他们的最小尺寸.因为这一步是如此复杂,让我们暂时把它放在一边,并使用一个更简单的方法,通过使用最大数量的重复.
通过这种简化,您的算法可能如下所示:

const existingRectangles = document.querySelectorAll('.Rectangle');
let repCount = 0; // Number of repetitions

do {
  var overlapping = false;
  var newPositionAndSize = generateRandomPositionAndSize();

  // Check for collision with any existing Rectangle.
  // Use a classic for loop to be able to break it
  // on the first collision (no need to check further)
  for (let i = 0: i < existingRectangles.length; i += 1) {
    if (checkCollision(existingRectangles[i], newPositionAndSize)) {
      overlapping = true;
      repCount += 1;
      break; // No need to check the rest of the list
    }
  }
} while (overlapping && repCount < 1000);

if (overlapping) {
  // If still overlapping, it means we could not find
  // a new empty spot (here because of max repetitions reached)
  showMessageWrapperIsFull();
} else {
  // If we checked through the entire list without raising
  // the overlapping flag, it means we have found
  // a suitable empty spot
  createNewRectangleAndInsertIt(newPositionAndSize);
}

相关问题