2014-07-26 6 views
6

Chciałbym wykryć, czy dwa obrócone elementy div są kolizyjne. Wiem, jak to zrobić, jeśli nie są obrócone, ale nie wiem, jak to zrobić, gdy w rzeczywistości są.Wykryj, czy dwa obrócone elementy div zderzają się przy użyciu JQuery

Próbowałem niektórych wtyczek kolizji, takich jak jQuery Collision (http://sourceforge.net/projects/jquerycollision/), ale nie działały, gdy div jest obrócony.

Dokonałem obrotu elementów div za pomocą właściwości transformacji CSS.

+0

Dlaczego nie używać czegoś takiego jak Famo.us do obsługi fizyki? Uważam, że obecnie obsługują tylko kolizje kołowe, ale https://github.com/DrClick/FamousBird używa kolizji prostokątnych.Sprawdź źródło, Luke. – Siddharth

+1

Słynny ptak tylko przecina prostokąt-koło. Ponieważ prawdopodobnie będziesz musiał zaimplementować to samodzielnie, znajdziesz [tę odpowiedź] (http://stackoverflow.com/a/115520/1166087) bardzo pomocne. Wszystko czego potrzebujesz to dodawanie i mnożenie. – Julian

+0

być może to pomóc http://shin.cl/pixelperfect/ – Alex

Odpowiedz

4

To nie jest w 100% dokładne, ale to działa w większości przypadków, użyłem algorytm z here:

function isUndefined(a) { 
    return a === undefined; 
} 

/** 
* Helper function to determine whether there is an intersection between the two polygons described 
* by the lists of vertices. Uses the Separating Axis Theorem 
* 
* @param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon 
* @param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon 
* @return true if there is any intersection between the 2 polygons, false otherwise 
*/ 
function doPolygonsIntersect (a, b) { 
    var polygons = [a, b]; 
    var minA, maxA, projected, i, i1, j, minB, maxB; 

    for (i = 0; i < polygons.length; i++) { 

     // for each polygon, look at each edge of the polygon, and determine if it separates 
     // the two shapes 
     var polygon = polygons[i]; 
     for (i1 = 0; i1 < polygon.length; i1++) { 

      // grab 2 vertices to create an edge 
      var i2 = (i1 + 1) % polygon.length; 
      var p1 = polygon[i1]; 
      var p2 = polygon[i2]; 

      // find the line perpendicular to this edge 
      var normal = { x: p2.y - p1.y, y: p1.x - p2.x }; 

      minA = maxA = undefined; 
      // for each vertex in the first shape, project it onto the line perpendicular to the edge 
      // and keep track of the min and max of these values 
      for (j = 0; j < a.length; j++) { 
       projected = normal.x * a[j].x + normal.y * a[j].y; 
       if (isUndefined(minA) || projected < minA) { 
        minA = projected; 
       } 
       if (isUndefined(maxA) || projected > maxA) { 
        maxA = projected; 
       } 
      } 

      // for each vertex in the second shape, project it onto the line perpendicular to the edge 
      // and keep track of the min and max of these values 
      minB = maxB = undefined; 
      for (j = 0; j < b.length; j++) { 
       projected = normal.x * b[j].x + normal.y * b[j].y; 
       if (isUndefined(minB) || projected < minB) { 
        minB = projected; 
       } 
       if (isUndefined(maxB) || projected > maxB) { 
        maxB = projected; 
       } 
      } 

      // if there is no overlap between the projects, the edge we are looking at separates the two 
      // polygons, and we know there is no overlap 
      if (maxA < minB || maxB < minA) { 
       console.log("polygons don't intersect!"); 
       return false; 
      } 
     } 
    } 
    return true; 
}; 

$('#r').click(function() { 
    var rota = Math.floor(Math.random() * 100), 
     rotb = Math.floor(Math.random() * 100), 
     pointsa = new Array(4), 
     pointsb = new Array(4); 

    $('#a').css('transform', 'rotateZ(' + rota + 'deg)'); 
    $('#b').css('transform', 'rotateZ(' + rotb + 'deg)'); 

    $('#a div').each(function(i) { 
     pointsa[i] = {x: parseInt($(this).offset().left), y: parseInt($(this).offset().top)}; 
    }); 

    $('#b div').each(function(i) { 
     pointsb[i] = {x: parseInt($(this).offset().left), y: parseInt($(this).offset().top)}; 
    }); 


    $('#s').val("intersection: " + doPolygonsIntersect(pointsb, pointsa).toString()); 
}); 

working fiddle

To nie jest najlepszy sposób robienia tego. Myślę, że to, co robi mój skrypt, daje w zasadzie losowy obrót pomiędzy 0 a 100 stopni, uzyskując pozycje xiy dla każdego rogu (używając div, możesz to zrobić z matematyką, również (nie mogę: D)) i uruchomić algorytm za pomocą tych współrzędnych.

+0

Tak, twierdzenie o osi rozdzielającej jest drogą do przebycia. Chociaż musisz zdobyć krawędzie obróconych pudełek. Aby to zrobić, nie można pozbyć się brudnej matematyki, aby uzyskać bieżący kąt obrotu przeanalizowany z css i ponownie obliczyć punkty div (ponieważ nie sądzę, że istnieje łatwiejszy sposób na uzyskanie pozycji krawędzi). Może to pomóc w ponownym tłumaczeniu i analizie rotacji: http://css-tricks.com/get-value-of-css-rotation-through-javascript/ – jbrosi

-1

Znalazłem overlaps.js przez yckart.

Zrobiłem skrzypce z obróconych div tutaj: http://jsfiddle.net/n3M5e/

Można zmienić rotację div w CSS siebie i wykrywanie nadal działa dobrze.

overlaps.js:

(function ($) { 
    $.fn.overlaps = function (obj) { 
     var elems = { 
      targets: [], 
      hits: [] 
     }; 
     this.each(function() { 
      var bounds = $(this).offset(); 
      bounds.right = bounds.left + $(this).outerWidth(); 
      bounds.bottom = bounds.top + $(this).outerHeight(); 

      var compare = $(obj).offset(); 
      compare.right = compare.left + $(obj).outerWidth(); 
      compare.bottom = compare.top + $(obj).outerHeight(); 

      if (!(compare.right < bounds.left || compare.left > bounds.right || compare.bottom < bounds.top || compare.top > bounds.bottom)) { 
       elems.targets.push(this); 
       elems.hits.push(obj); 
      } 
     }); 

     return elems; 
    }; 
}(jQuery)); 

nadzieję, że pomogło.

EDIT:

Dzięki @jbrosi, overlaps.js naprawdę nie działa bardzo dobrze z obróconych div.

+0

To naprawdę nie działa na polach obróconych - Zmieniłem warunków wyjściowych dla skrzypiec do stworzenia „fałszywego stanowiska”: http : //jsfiddle.net/jbrosi/D7vfd/ – jbrosi

+0

Ah Widzę, dziękuję za to, będę edytować moją odpowiedź mówiąc, że to – sam

-1

Poszukujesz wykrywania kolizji div.

Jeśli chcesz podnieść wydarzenie, musisz wielokrotnie testować, ale byłoby lepiej po prostu uruchomić funkcję nad wszystkimi elementami div

Demo próbka jest w http://jsfiddle.net/nGRwt/7/

Oto funkcja trzeba użyć

function collision($div1, $div2) { 
     var x1 = $div1.offset().left; 
     var y1 = $div1.offset().top; 
     var h1 = $div1.outerHeight(true); 
     var w1 = $div1.outerWidth(true); 
     var b1 = y1 + h1; 
     var r1 = x1 + w1; 
     var x2 = $div2.offset().left; 
     var y2 = $div2.offset().top; 
     var h2 = $div2.outerHeight(true); 
     var w2 = $div2.outerWidth(true); 
     var b2 = y2 + h2; 
     var r2 = x2 + w2; 

     if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false; 
     return true; 
    } 

Another Demo

Można również odwołać się do http://jsfiddle.net/98sAG/ wykrywania Collison.

Dla tego zastosowania poniższy kod:

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

nadzieję, że to pomoże Ci :)

+0

Czy ktokolwiek może uzasadnić, dlaczego został upomniany? – Mazzu

+0

Może to być spowodowane tym, że OP poprosił o wykrycie kolizji, gdy dwa symbole div zostały obrócone, a twoje nie - nie powiedziały btw – sam

+0

Ale to nie znaczy, że jest błędne lub niewłaściwe :( – Mazzu

Powiązane problemy