Vanilla JS Div碰撞检测 [英] Vanilla JS Div Collision Detection

查看:83
本文介绍了Vanilla JS Div碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对以下内容的实现可以在 jsfiddle.net

My implementation of the following can be found on jsfiddle.net

我有四个div。我的目标是使它们在页面上可拖动,但不允许它们彼此重叠。

I have four divs. My goal is to make them draggable around the page but NOT to allow them to overlap one another. Each can be dragged around the page with a mousemove listener.

container.addEventListener('mousemove',mouseMove);
  function mouseMove(e) {
    if (!mouseDown) {return;}
    let coords=e.target.getBoundingClientRect();
    let movX=e.movementX;
    let movY=e.movementY;
    if (!collision(movX,movY,e.target.classList[1],coords)){
      e.target.style.left=`${coords.left+movX}px`;
      e.target.style.top=`${coords.top+movY}px`;
    }
  }

严格来说,我的碰撞检测功能有效。我将 Collision事件输出到div,以便在拖动时可以在小提琴中看到它。但是,您仍然可以将div彼此拖动。

My collision detection function works, strictly speaking. I output the "Collision" event to a div so you can see this in the fiddle when you drag it around. BUT, you are still able to drag the divs on top of one another.

当您尝试将它们拉开时,它们会有点粘住,如果继续推动它们,它们将会重叠。此时,碰撞检测在true / false之间相当快地波动,因此我猜测这里可能有些怪异,但我无法弄清楚。

They kind of "stick" a little bit when you try to pull them apart, and if you keep pushing at them they'll overlap. The collision detection vacillates between true/false pretty rapidly at this point, so I'm guessing maybe some weirdness is going on here, but I can't figure it out.

我认为一个问题可能是冲突检测仅在边界相等时才输出冲突。也就是说,一旦发生碰撞并且一个元素在另一个元素内部,它将返回false。

I think one problem might be that the collision detection only outputs a collision when the borders are equal. That is, it returns false once a collision has happened and one element is inside another.

但是,我看不到鼠标移动e.movementX和e.movementY事件如何能够通过碰撞测试并移动div。

However, I can't see how my mousemove e.movementX and e.movementY events are able to get past the collision test and move the div.

推荐答案

对象将与多个对象发生碰撞,而不仅仅是1个。脚本将为您提供所有碰撞。但是,我猜想接受/删除它的逻辑取决于您想要实现的目标。从相交

You will have the object colliding with more than just 1. The script will give you all the collisions. But the logic to accept/move it or no i guess depends on what it is you are trying to achieve. Borrowed from intersects

脚本:

function mouseMove(e) {
  if (!mouseDown) {
    return;
  }
  let coords = e.target.getBoundingClientRect();
  let movX = e.movementX;
  let movY = e.movementY;

  collision(movX, movY, e.target.classList[1], coords) //check all collisions. Item can collide with more than one polygon.

  e.target.style.left = `${coords.left+movX}px`;
  e.target.style.top = `${coords.top+movY}px`;
  /* if (!) {

  }*/
}

function collision(newX, newY, movingPart, movingRect) {
  let takenPositions = []; //array of arrays of rects' L, R, Top, Bottom coords
  let newCoords = {
    id: movingPart,
    width: 100,
    height: 100,
    x: movingRect.left + newX,
    y: movingRect.top + newY
  };

  let collision = false;
  let collisions = []; //store collisions. 
  divs.forEach((d) => {
    if (d.classList[1] !== movingPart) { // a thing can't collide with itself
      let c = d.getBoundingClientRect();
      takenPositions.push({
        id: d.classList[1],
        width: 100,
        height: 100,
         x: c.left,//updated this part x,y are undefined :|
         y: c.top //and updated this
      });
    }
  });

  takenPositions.forEach((p) => {
    var tw = p.width;
    var th = p.height;
    var rw = newCoords.width;
    var rh = newCoords.height;
    if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
      collision = false;
    } else {
      var tx = p.x;
      var ty = p.y;
      var rx = newCoords.x;
      var ry = newCoords.y;
      rw += rx;
      rh += ry;
      tw += tx;
      th += ty;
      collision = ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry));
      collisions.push({
        parentId: newCoords.id,
        destId: p.id,
        collision: collision
      });
    }
  });
  let info = document.querySelector('div.info');
  info.innerHTML = "";
  collisions.forEach(function(element) {
    info.innerHTML += `${element.parentId} collision with ${element.destId} is ${element.collision}.  <br/>`;
  });
}

这篇关于Vanilla JS Div碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆