programing

jQuery/JavaScript 충돌 탐지

elecom 2023. 10. 20. 13:26
반응형

jQuery/JavaScript 충돌 탐지

2개인 경우 감지하는 방법<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();  

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

  • 상자 치수는 고정되어 있으므로 (내 코드에서 보는 것처럼) 반복적으로 읽을 필요가 없습니다.페이지 로드(변수로)를 읽고 변수만 읽을 수 있습니다.

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

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

이것이 가장 쉬운 방법이라고 생각합니다: https://plugins.jquery.com/overlaps/

이것은 독일어로 된 또 다른 것입니다: 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);

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

조금 늦었지만 비슷한 상황에 처했을 때 시도했던 이 방법을 사용해보셔도 될 것 같습니다.여기서의 장점은 플러그인이나 스크립트가 추가로 포함되어 있지 않고 성능이 부족한 폴링을 도입할 필요도 없다는 것입니다.이 방법은 Jquery의 드랍퍼블이 제공하는 내장된 방법과 이벤트를 사용합니다.

좋아요, 이미 말씀 드렸습니다. 해결 방법은 다음과 같습니다.두 개의 요소(내 경우에는 이미지)가 있는데 두 요소가 겹치거나 감지되지 않도록 하려면 두 요소를 떨어뜨릴 수 있도록 하고 서로 '수용'하도록 합니다.

$([div1, div2]).droppable(CONFIG_COLLISSION_PREVENTION_DROPPABLE);

'CONFIG_COLRISION_PREVENT_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' 핸들러는 'dropable' 플러그인의 'dropactivate' 및 'drop' 이벤트를 말합니다.

여기서 핵심은 '드롭' 콜백입니다.두 요소 중 하나가 겹쳐서 서로 겹칠 때마다 'drop'이 호출됩니다.이 곳은 사용자 지정 이벤트를 전송하거나 다른 작업을 호출할 수 있는 곳입니다(여기서는 드래그가 시작될 때 중첩된 요소의 위치를 초기 위치로 되돌리기로 선택했고, 이는 '활성화' 콜백에서 캡처되었습니다).

바로 그겁니다.여론조사도 없고 플러그인도 없고 내장된 이벤트만 있을 뿐입니다.

다른 최적화/확장이 가능합니다. 이것은 단순히 제 머리에서 나온 첫 번째 시도였습니다. :)

또한 '드롭오버' 및 '드롭아웃' 이벤트를 사용하여 두 요소가 서로 겹친다는 신호를 보내고 사용자에게 시각적 피드백을 생성할 수 있습니다.

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/

저도 같은 문제가 있었지만 오스카 갓슨의 답변 덕분에 작동하는 기능을 얻었습니다.쉬운 코딩을 위해 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#

연결할 수 있는 "충돌" 이벤트를 제공합니다. (또는 "돌림" 이벤트, 디브가 현재 포함된 다른 디브를 탈출하는지 확인합니다.)

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

언급URL : https://stackoverflow.com/questions/4230029/jquery-javascript-collision-detection

반응형