Detección de colisiones jQuery/JavaScript

Resuelto Chris Armstrong asked hace 13 años • 7 respuestas

¿ Cómo detectar si dos <div>elementos han chocado?

Los dos divs son cajas de colores simples que viajan perpendicularmente entre sí, por lo que no hay formas ni ángulos complicados.

Chris Armstrong avatar Nov 20 '10 05:11 Chris Armstrong
Aceptado

var overlaps = (function () {
    function getPositions( elem ) {
        var pos, width, height;
        pos = $( elem ).position();
        width = $( elem ).width();
        height = $( elem ).height();
        return [ [ pos.left, pos.left + width ], [ pos.top, pos.top + height ] ];
    }

    function comparePositions( p1, p2 ) {
        var r1, r2;
        r1 = p1[0] < p2[0] ? p1 : p2;
        r2 = p1[0] < p2[0] ? p2 : p1;
        return r1[1] > r2[0] || r1[0] === r2[0];
    }

    return function ( a, b ) {
        var pos1 = getPositions( a ),
            pos2 = getPositions( b );
        return comparePositions( pos1[0], pos2[0] ) && comparePositions( pos1[1], pos2[1] );
    };
})();

$(function () {
    var area = $( '#area' )[0],
        box = $( '#box0' )[0],
        html;
    
    html = $( area ).children().not( box ).map( function ( i ) {
        return '<p>Red box + Box ' + ( i + 1 ) + ' = ' + overlaps( box, this ) + '</p>';
    }).get().join( '' );

    $( 'body' ).append( html );
});
body {
    padding: 30px;
    color: #444;
    font-family: Arial, sans-serif;
}

h1 {
    font-size: 24px;
    margin-bottom: 20px;
}

#area {
    border: 2px solid gray;
    width: 500px;
    height: 400px;
    position: relative;
}

#area > div {
    background-color: rgba(122, 122, 122, 0.3);
    position: absolute;
    text-align: center;
    font-size: 50px;
    width: 60px;
    height: 60px;
}

#box0 {
    background-color: rgba(255, 0, 0, 0.5) !important;
    top: 150px;
    left: 150px;
}

#box1 {
    top: 260px;
    left: 50px;
}

#box2 {
    top: 110px;
    left: 160px;
}

#box3 {
    top: 200px;
    left: 200px;
}

#box4 {
    top: 50px;
    left: 400px;
}

p {
    margin: 5px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<h1>Detect overlapping with JavaScript</h1>
<div id="area">
    <div id="box0"></div>
    <div id="box1">1</div>
    <div id="box2">2</div>
    <div id="box3">3</div>
    <div id="box4">4</div>
</div>
Expandir fragmento

Idea general: obtienes el desplazamiento y la dimensión de las cajas y compruebas si se superponen.

Si quieres que se actualice, puedes usar setInterval:

function detectOverlapping() {
    // code that detects if the box overlaps with a moving box
    setInterval(detectOverlapping, 25);
}

detectOverlapping();  

Además, tenga en cuenta que puede optimizar la función para su ejemplo específico.

  • no es necesario leer las dimensiones del cuadro repetidamente (como hago yo en mi código) ya que son fijas. Puede leerlos al cargar la página (en una variable) y luego simplemente leer la variable

  • la posición horizontal del pequeño cuadro no cambia (a menos que el usuario cambie el tamaño de la ventana). Las posiciones verticales de las cajas del coche no cambian. Por lo tanto, esos valores tampoco tienen que leerse repetidamente, sino que también pueden almacenarse en variables.

  • No es necesario comprobar si la cajita se superpone con todas las cajas del coche en todo momento. Puede, basándose en su posición vertical, determinar en qué carril se encuentra actualmente la caja y probar solo la caja del automóvil específica de ese carril.

Šime Vidas avatar Nov 20 '2010 02:11 Šime Vidas

Creo que esta es la forma más sencilla: https://plugins.jquery.com/overlaps/

Aquí hay otro, en alemán: http://www.48design.de/news/2009/11/20/kollisionsabfrage-per-jquery-plugin-update-v11-8/

Yo les daría una oportunidad.

--ACTUALIZAR--

Realmente no puedo dedicarle tiempo a esto en este momento, pero puedo hacerlo cuando llegue a casa si nadie responde excepto tú; harías algo como:

setInterval(function(){
            //First step would be to get the offset of item 1 and item 2
            //Second would be to get the width of each
            //Third would be to check if the offset+width ever overlaps
                //the offset+width of the 2nd
            //Fourth would be, if so, do X or set a class...
        },10);
Oscar Godson avatar Nov 19 '2010 22:11 Oscar Godson

Puedes hacer esto usando getBoundingClientRect()

function isOverlapping(div1, div2){
    const div1 = div1.getBoundingClientRect();
    const div2 = div2.getBoundingClientRect();
    return (div1.right > div2.left && 
            div1.left < div2.right && 
            div1.bottom > div2.top && 
            div1.top < div2.bottom)
}
Rajat Bhatt avatar Apr 05 '2020 07:04 Rajat Bhatt