jQuery / JavaScript碰撞检测
如何检测两个<div>
元素是否碰撞?
两个div是简单的彩盒,相互垂直,所以没有复杂的形状或angular度。
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>
我相信这是最简单的方法: 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);
这有点晚了,但我想你可以用我在面对类似情况时所尝试的方法。 这里的好处是没有额外的插件或脚本,也不需要引入性能饥饿的轮询。 这种技术使用Jquery的droppable提供的内置方法和事件。
好的,足以说明,这里有解决方法:假如你有两个元素(在我的情况下是图像),而你不希望它们重叠或者检测到它们的时候,使这两个元素可以放下来,让它们“接受”彼此:
$([div1, div2]).droppable(CONFIG_COLLISSION_PREVENTION_DROPPABLE);
'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); } }
“激活”和“下降”处理程序指的是“droppable”插件的“dropactivate”和“drop”事件
在这里,关键是“下降”callback。 每当两个元素中的任何一个重叠并且彼此相互丢弃时,将会调用“drop”。 这是检测和采取行动的地方,可能是发送自定义事件或调用其他操作(我在这里select将重叠元素的位置恢复到拖动开始时的初始位置,这是在“激活”callback中捕获的)。
而已。 没有投票,没有插件,只是内置的事件。
那么,可以做其他的优化/扩展,这只是我脑海中的第一个工作:)
您还可以使用“延迟”和“丢失”事件来向用户发出信号并创build一个视觉反馈,即两个元素重叠,而他们可能仍在移动中。
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); } });
希望这可以帮助!
编辑:我已经写在我的网站上的博客文章。 这里有一个链接。 http://area36.nl/2014/12/creating-your-own-collision-detection-function-in-javascript/
那么我有同样的问题,但多亏了奥斯卡龙芯的答案我有一个function,工作。 我使用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 } }
它所做的基本上是获取element1
所有值,然后获取element2
所有值。 然后在一些计算的帮助下计算出所有的值。 然后在if
语句中比较element1
的平方和element2
的平方。 如果element1
值在element2
的左,右,上,下值之间。 如果这是真的,底部的代码被执行。
我自己碰到这个广义的问题,所以(完全披露)我为它做了一个插件。 对于关于静态对象的简单碰撞查询,试试这个:
http://sourceforge.net/projects/jquerycollision/
这可以让你得到一个重叠的碰撞箱的列表(或没有碰撞时没有):
hits = $("#collider").collision(".obstacles");
或者在“拖动”过程中发生碰撞事件,请使用以下命令:
http://sourceforge.net/apps/mediawiki/jquidragcollide/?source=navbar#collision
这给你一个“碰撞”事件来连接。 (或者是一个“突出”事件,看一个div是否会转义出当前包含它的另一个div。)
$(draggable).bind( "collision", function(event,ui) { ... } );
如果在运动过程中检查碰撞而不是拖动,只需重复调用原件即可。 注意:拖动的大小不能很好地resize。
邮政已经老了,可能会帮助别人…
function CheckDiv() { var ediv1 = document.getElementById('DIV1'); var ediv2 = document.getElementById('DIV2'); ediv1.top = $(ediv1).offset().top; ediv1.left = $(ediv1).offset().left; ediv1.right = Number($(ediv1).offset().left) + Number($(ediv1).width()); ediv1.bottom = Number($(ediv1).offset().top) + Number($(ediv1).height()); ediv2.top = $(ediv2).offset().top; ediv2.left = $(ediv2).offset().left; ediv2.right = Number($(ediv2).offset().left) + Number($(ediv2).width()); ediv2.bottom = Number($(ediv2).offset().top) + Number($(ediv2).height()); if (ediv1.right > ediv2.left && ediv1.left < ediv2.right && ediv1.top < ediv2.bottom && ediv1.bottom > ediv2.top) { alert("hi"); } if (ediv1.left > ediv2.left && ediv1.top > ediv2.top && ediv1.right < ediv2.right && ediv1.bottom < ediv2.bottom) { alert("hello"); } }