offsetTop vs. jQuery.offset (). top

82

Przeczytałem to offsetLefti offsetTopnie działa poprawnie we wszystkich przeglądarkach. jQuery.offset()ma dostarczyć abstrakcji, aby zapewnić poprawną wartość xbrowser.

To, co próbuję zrobić, to uzyskać współrzędne miejsca kliknięcia elementu względem lewego górnego rogu elementu.

Problem polega na tym, że jQuery.offset().topw FFX 3.6 faktycznie podaje mi wartość dziesiętną (w IE i Chrome te dwie wartości są zgodne).

To skrzypce pokazuje problem. Jeśli klikniesz dolny obraz, jQuery.offset().topzwraca 327,5, ale offsetTopzwraca 328.

Chciałbym myśleć, że offset()zwraca prawidłową wartość i powinienem go użyć, ponieważ będzie działać w różnych przeglądarkach. Jednak ludzie oczywiście nie mogą klikać ułamków dziesiętnych pikseli. Czy właściwy sposób określenia prawdziwego przesunięcia względem Math.round()przesunięcia, które zwraca jQuery? Powinienem użyć offsetTopzamiast tego, czy całkowicie innej metody?

Pigułki wybuchowe
źródło

Odpowiedzi:

15

Myślę, że masz rację, mówiąc, że ludzie nie mogą klikać pół pikseli, więc osobiście użyłbym zaokrąglonego offsetu jQuery ...

ChristopheCVB
źródło
4
Przesunięcie jQuery jest błędne, gdy używany jest zoom CSS
Mladen Janjetovic
77

Oto, o czym mówi jQuery API Doc.offset() :

Uzyskaj aktualne współrzędne pierwszego elementu lub ustaw współrzędne każdego elementu w zestawie dopasowanych elementów względem dokumentu .

Oto, o czym mówi MDN Web API.offsetTop :

offsetTop zwraca odległość bieżącego elementu względem góry węzła offsetParent

Oto, co .offset()zasadniczo robi jQuery v.1.11 podczas uzyskiwania coords:

var box = { top: 0, left: 0 };

// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof elem.getBoundingClientRect !== strundefined ) {
  box = elem.getBoundingClientRect();
}
win = getWindow( doc );
return {
  top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
  left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
};
  • pageYOffset intuicyjnie mówi, ile przewinięto stronę
  • docElem.scrollTop to rozwiązanie zastępcze dla IE <9 (które przy okazji nie są obsługiwane w jQuery 2)
  • docElem.clientTop jest szerokością górnej granicy elementu (w tym przypadku dokumentu)
  • elem.getBoundingClientRect()pobiera współrzędne względem widoku dokumentu (patrz komentarze). Może zwracać wartości ułamkowe, więc to jest źródło twojego błędu. Może również powodować błąd w IE <8, gdy strona jest powiększana. Aby uniknąć wartości ułamkowych, spróbuj obliczyć pozycję iteracyjnie

Wniosek

  • Jeśli chcesz, aby współrzędne względem węzła macierzystego , użyj element.offsetTop. Dodaj, element.scrollTopjeśli chcesz wziąć pod uwagę przewijanie przez rodzica. (lub użyj jQuery .position () jeśli jesteś fanem tej biblioteki)
  • Jeśli potrzebujesz współrzędnych względem rzutni, użyj element.getBoundingClientRect().top. Dodaj, window.pageYOffsetjeśli chcesz wziąć pod uwagę przewijanie dokumentu. Nie musisz odejmować dokumentów, clientTopjeśli dokument nie ma obramowania (zwykle nie ma), więc masz pozycję względem dokumentu
  • Odejmij, element.clientTopjeśli nie uważasz obramowania elementu za część elementu
Jan Turoň
źródło
Element.getBoundingClientRect()podaje pozycje względem widoku , a nie dokumentu
Klaus
@Klaus: czy mógłbyś wyjaśnić, na czym dokładnie polega różnica?
Jan Turoň
2
@ JanTuroň: Różnica polega na tym, że odnosi się ona do górnej części okna przeglądarki, a nie do „prawdziwej góry” dokumentów. Oznacza to, że zwróci wartości ujemne, jeśli na przykład przewiniesz go do góry poza górną część okna.
Ryan Badour,
5

Spróbuj tego: parseInt(jQuery.offset().top, 10)

Steve Chan
źródło
Chciałbym, żeby był jakiś powód, więc mógłbym zagłosować na
ciebie
2

Możliwe, że offsetmoże być liczbą niecałkowitą, używając emjako jednostki miary, względnej font-sizesw% .

Teoretyzuję również, że offsetmoże nie być liczbą całkowitą, gdy zoomnie jest, 100%ale to zależy od tego, jak przeglądarka obsługuje skalowanie.

Emyr
źródło
2
jeśli powiększenie nie jest 100%, offset (). top da ci mnóstwo innych problemów ... bugs.jquery.com/ticket/8362
commonpike
-1

Możesz użyć, parseInt(jQuery.offset().top)aby zawsze używać wartości całkowitej (prymityw - int) we wszystkich przeglądarkach.

ShankarSangoli
źródło
1
Czy parseInt () zaokrągla podwojenie lub obcina je?
Tabletki wybuchowe,
Po prostu weźmie całkowitą część liczby i będzie taka sama we wszystkich przeglądarkach.
ShankarSangoli,
OP stwierdza, że ​​w jednej przeglądarce daje 327,5, podczas gdy w innej daje 328. Więc jeśli weźmiesz po prostu część całkowitą (obcięcie), sam OP jest przykładem tego, że nie jest taki sam we wszystkich przeglądarkach. W tym przykładzie przynajmniej musiałoby zaokrąglić obie strony, aby podać tę samą liczbę.
Jimbo Jonny