Vanilla JS Div Collision Detection

折月煮酒 提交于 2019-12-02 05:13:52

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

script:

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/>`;
  });
}

This is a bit more complex than it looks.

Essentially what you need to do is get both sets of coordinates, those for the current (moving) element, and the one with which it has collided. Once a collision is detected, find out which axis has the smallest difference, then snap those coordinates.

var ac = a.getBoundingClientRect(); // coordinates for element 'a'
var bc = b.getBoundingClientRect(); // and 'b'

// assuming both boxes are same size...
// if not, use your existing collision code.

if(Math.abs(ac.top - bc.top) < ac.height && Math.abs(ac.left - bc.left) < ac.width) {
// collision here...

    if(Math.abs(ac.top - bc.top) < Math.abs(ac.left - bc.left)) {
    // vartical offset is smaller, so snap 'y's

        if(ac.top < bc.top) { // a is above b, so snap a's bottom to b's top
            a.style.top = bc.top - ac.height - 1 + 'px';
        }
        else {
            a.style.top = bc.top + bc.height + 1 + 'px';
        }

    }
    else { // here, horizontal offset is smaller, so snap 'x's

        if(ac.left < bc.left) { // a is to the left of b, so snap a's right to b's left
            a.style.left = bc.left - ac.width - 1 + 'px';
        }
        else {
            a.style.left = bc.left + bc.width + 1 + 'px';
        }

    }

}

That should solve your problem...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!