简体   繁体   中英

How to detect if two divs are touching/ collision detection

I have searched all over Google and here for this but haven't found an answer that suits my problem

(This is a really simplified explanation) I have two divs which can be moved by the user (using JavaScript and click events) I need to detect if the two divs are touching/on top of each other and if they are to trigger a function I have seen answers on here but they all use jQuery and I want to use pure JS

Something that might be useful is that both divs have position absolute and different z-indexes set in css

EDIT: to clear things up since my explanation was very poor one of the two divs is stationary and the second can only move in the Y direction but the div that moves in the Y direction is rotating using a case animation

There's probably a better way (this isnt very DRY) but it should work, simply replace "div1" and "div2" with your div IDs:

let div1 = document.getElementById('div1').getBoundingClientRect();
let div1Top = div1.top;
let div1Left = div1.left;
let div1Right = div1.right
let div1Bottom = div1.bottom

let div2 = document.getElementById('div2').getBoundingClientRect();
let div2Top = div1.top;
let div2Left = div1.left;
let div2Right = div1.right
let div2Bottom = div1.bottom

if ((div2Top > div1Top && div2Top < div1Bottom)||(div2Bottom > div1Top && div2Bottom < div1Bottom)) {
  let verticalMatch = true
} else{
  let verticalMatch = false
}

if ((div2Right > div1Left && div2Right < div1Right)||(div2Left < div1Right && div2Left > div1Left)) {
  let horizontalMatch = true
} else {
  let horizontalMatch = false
}

if (horizontalMatch && vertialMatch){
  let intersect = true
} else {
  let intersect = false
}

在两个 div 上尝试Element.getBoundingClientRect()并使用它们的坐标进行碰撞检测

This is similar to the current correct answer but what I did to solve this problem follows.

let d1 = document.getElementById('div1').getBoundingClientRect();
let d2 = document.getElementById('div2').getBoundingClientRect();

function touching(div1,div2){
    let ox = Math.abs(d1.x - d2.x) < (d1.x < d2.x ? d2.width : d1.width);
    let ox = Math.abs(d1.y - d2.y) < (d1.y < d2.y ? d2.height : d1.height);
    return ox && oy;
}

var t = touching(d1,d2) // should return whether they are touching

Note that this function will not work with transformations very well.

You could use the process described in this post by Anand Thangappan to get the computed location of the element. You could then get the computed width and height using getComputedStyle() ( documentation here ), and test if they intersect using simple inequality checks.

EDIT: Alternatively, you can just read their location values directly, since you're using absolute position. Then you can skip the more complicated way of getting the computed location of the element.

Since you are allowing the user to move the DIVs and they're both absolute, you must have access to the STYLE attributes of the DIVs.

Get the the top, left, width and height properties.

Calculate the bottom and right properties. Now you have all four corner coordinates.

Since they're both rectangles, you can check to see if the top or bottom of dev A is between the top and bottom of div B AND if the left or right is between the left and right of dev B.

The one good part about this is that you only have to check A -> B because any overlap would be detected in both tests.

This works because of the rectilinear nature of the shapes. It would be more complicated if these were triangles or pentagons, or if they were not convex shapes.

It's worth noting that if you're using CSS / JS animation, you may wish to enlarge the 'collision area' if you have objects moving at high speed. Otherwise, items might go through between checks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM