Как определить, столкнулись ли два элемента <div>
?
Два div - это простые цветные коробки, перемещающиеся перпендикулярно друг другу, поэтому нет сложных форм или углов.
Как определить, столкнулись ли два элемента <div>
?
Два div - это простые цветные коробки, перемещающиеся перпендикулярно друг другу, поэтому нет сложных форм или углов.
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/
Я бы попробовал.
- ОБНОВЛЕНИЕ -
Я не могу тратить в это время на это прямо сейчас, но могу, когда вернусь домой, если никто не ответит, но вы сделаете что-то вроде:
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
// position back to it original position/offset
// (which was captured in the 'activate' handler)
$(ui.draggable).animate({
top: originatingOffset.top + "px",
left: originatingOffset.left + "px"
}, 300);
}
}
Обработчики "активировать" и "отбрасывать" ссылаются на события "dropactivate" и "drop" плагина "droppable"
Здесь ключ - это обратный вызов "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);
}
});
Надеюсь, это поможет!
EDIT: Я написал сообщение в блоге на своем веб-сайте. Вот ссылка на него. http://area36.nl/2014/12/creating-your-own-collision-detection-function-in-javascript/
Ну, у меня была такая же проблема, но благодаря ответу Оскара Годсона я получил функцию, которая работает. Я использовал Jquery для легкого кодирования и потому, что я ленив; Я помещаю функцию в другую функцию, которая запускается каждую секунду, поэтому помните об этом.
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) {
...
}
);
Если вы проверяете конфликты во время движения, кроме перетаскивания, просто вызывайте оригинал повторно, это довольно быстро. Примечание: перетаскивание не очень хорошо воспроизводится при изменении размера.
Сообщение старое, может быть, это поможет кому-то...
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");
}
}