Development Tip

jQuery / JavaScript 충돌 감지

yourdevel 2020. 10. 19. 12:52
반응형

jQuery / JavaScript 충돌 감지


<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>

일반적인 아이디어-상자의 오프셋과 치수를 확인하고 겹치는 지 확인합니다.

업데이트하려면 다음을 사용할 수 있습니다 setInterval.

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

detectOverlapping();  

또한 특정 예제에 대해 함수를 최적화 할 수 있습니다.

  • 상자 치수가 고정되어 있기 때문에 (내 코드 에서처럼) 반복해서 읽을 필요가 없습니다. 페이지로드시 (변수로) 읽을 수 있으며 변수를 읽을 수 있습니다.

  • 작은 상자의 가로 위치는 변경되지 않습니다 (사용자가 창 크기를 조정하지 않는 한). 자동차 상자의 수직 위치는 변경되지 않습니다. 따라서 이러한 값은 반복적으로 읽을 필요가 없지만 변수에 저장할 수도 있습니다.

  • 작은 상자가 항상 모든 자동차 상자와 겹치는 지 테스트 할 필요가 없습니다. 수직 위치를 기반으로 상자가 현재 어느 차선에 있는지 파악하고 해당 차선에서 특정 자동차 상자 만 테스트 할 수 있습니다.


이것이 가장 쉬운 방법이라고 생각합니다 : 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'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);
     }
}

'activate'및 'drop'핸들러는 "droppable"플러그인의 'dropactivate'및 'drop'이벤트를 참조합니다.

여기서 핵심은 'drop'콜백입니다. 두 요소 중 하나가 겹치고 서로 위에 놓일 때마다 'drop'이 호출됩니다. 이것은 감지하고 조치를 취하는 곳이며, 사용자 정의 이벤트를 보내거나 다른 조치를 호출 할 수 있습니다 (여기서는 '활성화'콜백에서 캡처 된 드래그가 시작될 때 겹치는 요소의 위치를 ​​초기 위치로 되돌 리도록 선택했습니다).

그게 다야. 폴링도, 플러그인도, 내장 이벤트 만 있습니다.

글쎄, 다른 최적화 / 확장이있을 수 있습니다. 이것은 단순히 내 머리에서 나온 첫 번째 샷이었습니다 :)

You can also use the 'dropover' and 'dropout' events to signal and create a visual feedback to the user that two elements are overlapping, while they may be still on the move.

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);
    }
});

Hope this helps!


EDIT: I have written a blog post on my website. Here a link to it. http://area36.nl/2014/12/creating-your-own-collision-detection-function-in-javascript/

Well I had the same problem but thanks to the answer of Oscar Godson I got a function that works. I used Jquery for easy coding and because i'm lazy ;p. I put the function in a other function that is fired every second so keep that in mind.

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
    }
}

What it does is basically it gets all the values of element1 and then get all the values of element2. Then with the help of some calculations it figures out all the values. Then in the if statement it compares the square of element1 to the square of element2. If the values of element1 are between the left, right, top and bottom values of element2. If that is true the code in the bottom is executed.


I ran into this generalized issue myself, so (full disclosure) I made a plugin for it. For simple collision queries about static objects, try this:

http://sourceforge.net/projects/jquerycollision/

Which allows you to get a list of overlapping collision boxes (or none if there's no collision):

hits = $("#collider").collision(".obstacles");

Or to get a collision event during "dragging", use this:

http://sourceforge.net/apps/mediawiki/jquidragcollide/?source=navbar#collision

Which gives you a "collision" event to connect to. (Or a "protrusion" event, to see if a div escapes another div that currently contains it.)

$(draggable).bind( 
   "collision",
   function(event,ui) {
      ...
   }
);

If you are checking collisions during motion other than dragging, just call the original repeatedly, it's pretty quick. Note: the dragging one doesn't play nicely with resizing.


Post is old, May be it help someone...

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");
    }
}

참고URL : https://stackoverflow.com/questions/4230029/jquery-javascript-collision-detection

반응형