jQuery/JavaScript碰撞检测

Chr*_*ong 75 html javascript jquery collision-detection

如何检测两个<div>元素是否发生碰撞?

两个div是相互垂直的简单彩色盒子,因此没有复杂的形状或角度.

Šim*_*das 70

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 );
});
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

一般的想法 - 你得到盒子的偏移和尺寸,并检查它们是否重叠.

如果要更新,可以使用setInterval:

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

detectOverlapping();  
Run Code Online (Sandbox Code Playgroud)

另请注意,您可以针对特定示例优化功能.

  • 你不必重复读取盒子尺寸(就像我在我的代码中那样),因为它们是固定的.您可以在页面加载(变量)中读取它们,然后只读取变量

  • 小方框的水平位置不会改变(除非用户调整窗口大小).汽车箱的垂直位置不会改变.因此,这些值也不必重复读取,但也可以存储到变量中.

  • 您无需一直测试小方框是否与所有车厢重叠.您可以 - 根据其垂直位置 - 确定箱子当前在哪条车道上,并仅测试该车道的特定车厢.

  • 这是一个非常好的小提琴,但你认为在第4行使用`$ .offset()`而不是`$ .position()`并不是更好吗?这样它应该可以用于检查DOM中所有元素的冲突,而不仅仅是处理兄弟元素. (4认同)

Osc*_*son 17

我相信这是最简单的方法:http: //plugins.jquery.com/project/collidable

这是另一个用德语:http: //www.48design.de/news/2009/11/20/kollisionsabfrage-per-jquery-plugin-update-v11-8/

我试试看.

--UPDATE--

我现在不能在任何时间花在它上面,但是当我回到家时,如果没有人回答你,我可以;我做的事情如下:

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);
Run Code Online (Sandbox Code Playgroud)


Raj*_*att 10

您可以使用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)
}
Run Code Online (Sandbox Code Playgroud)


小智 7

它有点晚了,但我想你可以使用我在面对类似情况时尝试的这种方法.这里的优点是没有额外的插件或涉及的脚本,你也不必将性能饥饿的轮询引入其中.此技术使用Jquery的droppable提供的内置方法和事件.

好吧,足够的说,这里是解决方案技巧:假设你有两个元素(在我的情况下是图像)并且你不希望它们重叠或检测它们的时候,让这两个元素成为可放置的并使它们成为'接受'彼此:

$([div1, div2]).droppable(CONFIG_COLLISSION_PREVENTION_DROPPABLE);
Run Code Online (Sandbox Code Playgroud)

'CONFIG_COLLISSION_PREVENTION_DROPPABLE'看起来像这样:

var originatingOffset = null;
CONFIG_COLLISSION_PREVENTION_DROPPABLE = {
    tolerance: "touch",
    activate : function (event, ui) {
        // note the initial position/offset when drag starts
        // will be usedful in drop handler to check if the move
        // occurred and in cae overlap occurred, restore the original positions.
        originatingOffset = ui.offset;
    },
    drop : function (event, ui) {
            // If this callback gets invoked, the overlap has occurred. 
            // Use this method to either generate a custom event etc.

            // Here, i used it to nullify the move and resetting the dragged element's 
            // position back to it's original position/offset
            // (which was captured in the 'activate' handler)
        $(ui.draggable).animate({
            top: originatingOffset.top + "px",
            left: originatingOffset.left + "px"
        }, 300);
     }
}
Run Code Online (Sandbox Code Playgroud)

'activate'和'drop'处理程序引用"droppable"插件的'dropactivate'和'drop'事件

这里的关键是'drop'回调.只要两个元素中的任何一个重叠并且它们相互重叠,就会调用"drop".这是检测和执行操作的地方,可能是发送自定义事件或调用其他操作(我在这里选择将重叠元素的位置恢复到拖动开始时的初始位置,这是在'激活'回调中捕获的).

而已.没有轮询,没有插件,只有内置事件.

好吧,可以进行其他优化/扩展,这只是我头脑中的第一个工作:)

您还可以使用"dropover"和"dropout"事件来向用户发出信号并创建两个元素重叠的视觉反馈,同时它们可能仍处于移动状态.

var CLASS_INVALID = "invalid";
// .invalid { border: 1px solid red; }
...
$.extend(CONFIG_COLLISSION_PREVENTION_DROPPABLE, {
   over : function (event, ui) {
        // When an element is over another, it gets detected here;
        // while it may still be moved.
        // the draggable element becomes 'invalid' and so apply the class here
        $(ui.draggable).addClass(CLASS_INVALID);
    },
    out : function(event, ui) {               
         // the element has exited the overlapped droppable now
         // So element is valid now and so remove the invalid class from it
         $(ui.draggable).removeClass(CLASS_INVALID);
    }
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


Gek*_*len 5

编辑:我在我的网站上写了一篇博文.这是一个链接. http://area36.nl/2014/12/creating-your-own-collision-detection-function-in-javascript/

我有同样的问题但是由于奥斯卡龙芯的答案我得到了一个有效的功能.我使用Jquery进行简单的编码,因为我很懒; p.我把函数放在另一个每秒触发的函数中,所以记住这一点.

function collidesWith (element1, element2) {
    var Element1 = {};
    var Element2 = {};

    Element1.top = $(element1).offset().top;
    Element1.left = $(element1).offset().left;
    Element1.right = Number($(element1).offset().left) + Number($(element1).width());
    Element1.bottom = Number($(element1).offset().top) + Number($(element1).height());

    Element2.top = $(element2).offset().top;
    Element2.left = $(element2).offset().left;
    Element2.right = Number($(element2).offset().left) + Number($(element2).width());
    Element2.bottom = Number($(element2).offset().top) + Number($(element2).height());

    if (Element1.right > Element2.left && Element1.left < Element2.right && Element1.top < Element2.bottom && Element1.bottom > Element2.top) {
        // Do your stuff here
    }
}
Run Code Online (Sandbox Code Playgroud)

它的作用基本上是获取所有值,element1然后得到所有的值element2.然后在一些计算的帮助下,它计算出所有的值.然后在if声明中它比较广场element1的平方element2.如果值element1在左侧,右侧,顶部和底部之间element2.如果是这样,则执行底部的代码.