2017-01-08 8 views
0

내 구현은 다음과 같습니다. jsfiddle.net바닐라 JS 부서 충돌 감지

4 개의 div가 있습니다. 내 목표는 페이지 주위를 드래그 할 수있게하는 것이지만 서로 겹치지 않도록하는 것입니다. 각각은 mousemove 리스너를 사용하여 페이지 주위로 드래그 할 수 있습니다.

container.addEventListener('mousemove',mouseMove); 
    function mouseMove(e) { 
    if (!mouseDown) {return;} 
    let coords=e.target.getBoundingClientRect(); 
    let movX=e.movementX; 
    let movY=e.movementY; 
    if (!collision(movX,movY,e.target.classList[1],coords)){ 
     e.target.style.left=`${coords.left+movX}px`; 
     e.target.style.top=`${coords.top+movY}px`; 
    } 
    } 

내 충돌 감지 기능은 엄밀히 말하면 작동합니다. div에 "Collision"이벤트를 출력하므로 주위를 드래그 할 때이를 볼 수 있습니다. 하지만 div를 서로 위에 드래그 할 수는 있습니다.

당신이 그것들을 떼어 낼려고 할 때 조금씩 달라 붙습니다. 충돌 감지는이 시점에서 매우 빠르게 진실/거짓 사이를 움직입니다. 그래서 나는 아마도 여기에 어떤 이상 함이 있을지 모른다고 추측합니다. 그러나 나는 그것을 알 수 없습니다.

국경이 같을 때 충돌 감지가 충돌 만 출력한다는 것이 하나의 문제라고 생각합니다. 즉, 충돌이 발생하고 한 요소가 다른 요소 안에 있으면 오류를 반환합니다.

그러나 mousemove e.movementX 및 e.movementY 이벤트가 충돌 테스트를 통과하고 div를 이동하는 방법을 알 수 없습니다.

+0

당신의 예에서, 당신의 '항목은'광장입니다. 항상 그렇습니까? – allnodcoms

+0

그들은 직사각형 일 수도 있습니다. – thmsdnnr

+0

아래에 제시 한 대답은 모두 같은 크기 인 한 직사각형을 처리합니다. 그렇지 않다면 약간의 바이올린이 필요할 수도 있습니다 ... – allnodcoms

답변

0

문제를 해결해야

var ac = a.getBoundingClientRect(); // coordinates for element 'a' 
var bc = b.getBoundingClientRect(); // and 'b' 

// assuming both boxes are same size... 
// if not, use your existing collision code. 

if(Math.abs(ac.top - bc.top) < ac.height && Math.abs(ac.left - bc.left) < ac.width) { 
// collision here... 

    if(Math.abs(ac.top - bc.top) < Math.abs(ac.left - bc.left)) { 
    // vartical offset is smaller, so snap 'y's 

     if(ac.top < bc.top) { // a is above b, so snap a's bottom to b's top 
      a.style.top = bc.top - ac.height - 1 + 'px'; 
     } 
     else { 
      a.style.top = bc.top + bc.height + 1 + 'px'; 
     } 

    } 
    else { // here, horizontal offset is smaller, so snap 'x's 

     if(ac.left < bc.left) { // a is to the left of b, so snap a's right to b's left 
      a.style.left = bc.left - ac.width - 1 + 'px'; 
     } 
     else { 
      a.style.left = bc.left + bc.width + 1 + 'px'; 
     } 

    } 

} 

단지 ... 1. 스크립트는 당신에게 모든 충돌을 줄 것이다. 그러나 그것을 받아들이거나 움직이는 논리는 당신이 성취하고자하는 바에 달려 있습니다. intersects

스크립트에서 빌린 :

function mouseMove(e) { 
    if (!mouseDown) { 
    return; 
    } 
    let coords = e.target.getBoundingClientRect(); 
    let movX = e.movementX; 
    let movY = e.movementY; 

    collision(movX, movY, e.target.classList[1], coords) //check all collisions. Item can collide with more than one polygon. 

    e.target.style.left = `${coords.left+movX}px`; 
    e.target.style.top = `${coords.top+movY}px`; 
    /* if (!) { 

    }*/ 
} 

function collision(newX, newY, movingPart, movingRect) { 
    let takenPositions = []; //array of arrays of rects' L, R, Top, Bottom coords 
    let newCoords = { 
    id: movingPart, 
    width: 100, 
    height: 100, 
    x: movingRect.left + newX, 
    y: movingRect.top + newY 
    }; 

    let collision = false; 
    let collisions = []; //store collisions. 
    divs.forEach((d) => { 
    if (d.classList[1] !== movingPart) { // a thing can't collide with itself 
     let c = d.getBoundingClientRect(); 
     takenPositions.push({ 
     id: d.classList[1], 
     width: 100, 
     height: 100, 
     x: c.left,//updated this part x,y are undefined :| 
     y: c.top //and updated this 
     }); 
    } 
    }); 

    takenPositions.forEach((p) => { 
    var tw = p.width; 
    var th = p.height; 
    var rw = newCoords.width; 
    var rh = newCoords.height; 
    if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) { 
     collision = false; 
    } else { 
     var tx = p.x; 
     var ty = p.y; 
     var rx = newCoords.x; 
     var ry = newCoords.y; 
     rw += rx; 
     rh += ry; 
     tw += tx; 
     th += ty; 
     collision = ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry)); 
     collisions.push({ 
     parentId: newCoords.id, 
     destId: p.id, 
     collision: collision 
     }); 
    } 
    }); 
    let info = document.querySelector('div.info'); 
    info.innerHTML = ""; 
    collisions.forEach(function(element) { 
    info.innerHTML += `${element.parentId} collision with ${element.destId} is ${element.collision}. <br/>`; 
    }); 
} 
+0

교차로에 대한 링크를 가져 주셔서 감사합니다. 지금 당장은 매우 치밀 할 수도 있지만, 어떤 이유로 코드가 요소들 사이의 충돌을 기록하지 않습니다 : [바이올렛] (https://jsfiddle.net/thmsdnnr/t5yn37d4/3/) – thmsdnnr

+0

@thomasdanner 죄송합니다. 암호. 'takenPosition' x와 y 값은'x : c.left, y : c.top'입니다. 방금 바이올린에서 해봤 어. 나에게 알리 라. .. – Searching

0

이것은보기보다 조금 복잡합니다.

기본적으로 수행해야 할 작업은 현재 좌표 (이동) 요소와 충돌 한 좌표를 모두 가져 오는 것입니다. 충돌이 감지되면 어느 축의 차이가 가장 작은 지 확인한 다음 해당 좌표를 스냅합니다. 당신은보다 더 많은 충돌 객체를해야합니다