Pytanie Uzyskaj względną pozycję między 2 elementami DOM za pomocą JavaScript


Zaimplementowałem zestaw przeciągalnych elementów, które można upuścić do niektórych kontenerów za pomocą jQuery. Potrzebuję animacji, która przenosi element do określonego kontenera bez interakcji użytkownika. Problem polega na tym, że elementy i pojemniki upuszczające są całkowicie różne części DOM i najczęściej pozycjonowane za pomocą pływaka.

Potrzebuję tylko trochę kodu, aby uzyskać bezwzględną różnicę pozycji między dwoma pływającymi elementami DOM, najlepiej używając jQuery. Odkryłem tylko, że niektóre hacki parsują w górę DOM, ale zawsze są bardzo specyficzne dla przeglądarki (np. "To nie działa dobrze z Firefoksem lub IE lub czymkolwiek").

Najlepsze byłoby coś takiego:

var distance = getDistance(element1, element2);

lub w notacji jQuery:

var distance = $(element1).distanceTo($(element2));

14
2017-10-22 12:37


pochodzenie




Odpowiedzi:


Nigdy nie używałam jQuery, tylko sprawdziłem API, więc mogę założyć, że możesz wykonać następujące czynności:

var o1 = $ (element1) .offset ();
var o2 = $ (element2) .offset ();
var dx = o1.left - o2.left;
var dy = o1.top - o2.top;
var distance = Math.sqrt (dx * dx + dy * dy);

22
2017-10-22 12:49



To nie zadziała, ponieważ .offset () zwraca tylko względną pozycję do elementu nadrzędnego. Ponieważ elementy macierzyste nie są takie same, wartości nie mogą być używane. Część odległości po przekątnej nie jest ważna, spodziewałem się lewych i najwyższych wartości ;-) - davil
Cóż, nie zgadzam się z tobą. Zgodnie z odniesieniem do jQuery (docs.jquery.com/CSS), offset otrzymuje "bieżące przesunięcie pierwszego dopasowanego elementu względem rzutni". rzutnia jest słowem kluczowym, nie jest offsetParent - Sergey Ilinsky
Przykład na stronie z przesunięciem jest dość mylący. Przykłady są ładowane do elementów iframe, co sprawia, że ​​wygląda tak, jakby pozycja była tylko względna względem elementu nadrzędnego, podczas gdy w rzeczywistości jest względna w stosunku do dokumentu (w tym przypadku elementu iframe) - nickf
Mogę zweryfikować tę odpowiedź jako poprawną: zobacz mój działający przykład tutaj: jsbin.com/ojede - nickf
$ (elem1) .offset ({relativeTo: elem2}) - Sugendran


Korzystanie z czystego javascript.

var dx = obj1.offsetLeft - obj2.offsetLeft;
var dy = obj1.offsetTop - obj2.offsetTop;
var distance = Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2));

1
2017-10-22 12:59



Tak samo jak w przypadku odpowiedzi Sergeya ... offsetLeft i offsetTop działają tylko w tym samym elemencie rodzica. - davil


A co z poniższymi?

var isIE = navigator.appName.indexOf("Microsoft") != -1;

function getDistance(obj1, obj2){
    var obj1 = document.getElementById(obj1);
    var obj2 = document.getElementById(obj2);
    var pos1 = getRelativePos(obj1);
    var pos2 = getRelativePos(obj2);
    var dx = pos1.offsetLeft - pos2.offsetLeft;
    var dy = pos1.offsetTop - pos2.offsetTop;
    return {x:dx, y:dy};
}
function getRelativePos(obj){
var pos = {offsetLeft:0,offsetTop:0};
while(obj!=null){
    pos.offsetLeft += obj.offsetLeft;
    pos.offsetTop += obj.offsetTop;
    obj = isIE ? obj.parentElement : obj.offsetParent;
}
return pos;
}
//
var obj = getDistance("element1","element2")
alert(obj.x+" | "+obj.y);

1
2017-10-22 13:38



Że isIE test nie jest potrzebny. Dlaczego nie tylko obj = obj.offsetParent || obj.parentElement (lub cokolwiek jest wymagane). - alex