offsetTop vs. jQuery.offset (). top

82

Ich habe das gelesen offsetLeftund offsetToparbeite nicht in allen Browsern richtig. jQuery.offset()soll eine Abstraktion dafür bereitstellen, um den korrekten Wert xbrowser bereitzustellen.

Ich versuche, die Koordinaten zu ermitteln, an denen ein Element relativ links oben im Element angeklickt wurde.

Das Problem ist, jQuery.offset().topdass ich in FFX 3.6 tatsächlich einen Dezimalwert bekomme (in IE und Chrome stimmen die beiden Werte überein).

Diese Geige zeigt das Problem. Wenn Sie auf das untere Bild klicken, wird jQuery.offset().top327,5, aber offsetTop328 zurückgegeben.

Ich würde gerne denken, dass dies offset()den richtigen Wert zurückgibt und ich sollte ihn verwenden, da er in allen Browsern funktioniert. Menschen können jedoch offensichtlich nicht auf Dezimalstellen von Pixeln klicken. Ist der richtige Weg, um den wahren Versatz zu Math.round()dem Versatz zu bestimmen, den jQuery zurückgibt? Sollte ich offsetTopstattdessen oder eine andere Methode verwenden?

Explosionspillen
quelle

Antworten:

15

Ich denke, Sie haben Recht, wenn Sie sagen, dass die Leute nicht auf halbe Pixel klicken können. Ich persönlich würde also einen gerundeten jQuery-Offset verwenden ...

ChristopheCVB
quelle
4
jQuery Offset ist fehlerhaft, wenn CSS-Zoom verwendet wird
Mladen Janjetovic
76

Dies ist, was jQuery API Doc über Folgendes sagt .offset():

Rufen Sie die aktuellen Koordinaten des ersten Elements ab oder legen Sie die Koordinaten jedes Elements in der Gruppe der übereinstimmenden Elemente relativ zum Dokument fest .

Dies sagt die MDN-Web-API über .offsetTop:

offsetTop gibt den Abstand des aktuellen Elements relativ zum oberen Rand des Knotens offsetParent zurück

Dies ist, was jQuery v.1.11 im .offset()Grunde tut, wenn Sie die Koordinaten erhalten:

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 Intuitiv sagt, wie viel die Seite gescrollt wurde
  • docElem.scrollTop ist der Fallback für IE <9 (die in jQuery 2 übrigens nicht unterstützt werden)
  • docElem.clientTop ist die Breite des oberen Randes eines Elements (in diesem Fall des Dokuments)
  • elem.getBoundingClientRect()die Koordinaten relativ zum bekommt Dokument Ansichtsfenster (siehe Kommentare). Es kann Bruchwerte zurückgeben, daher ist dies die Quelle Ihres Fehlers. Es kann auch einen Fehler im IE <8 verursachen, wenn die Seite gezoomt wird. Versuchen Sie, die Position iterativ zu berechnen, um Bruchwerte zu vermeiden

Fazit

  • Wenn Sie Koordinaten relativ zum übergeordneten Knoten wünschen , verwenden Sie element.offsetTop. Fügen element.scrollTopSie hinzu, wenn Sie das übergeordnete Scrollen berücksichtigen möchten. (oder verwenden Sie jQuery .position (), wenn Sie ein Fan dieser Bibliothek sind)
  • Wenn Sie Koordinaten relativ zum Ansichtsfenster wünschen, verwenden Sie element.getBoundingClientRect().top. Fügen window.pageYOffsetSie hinzu, wenn Sie das Scrollen des Dokuments berücksichtigen möchten. Sie müssen keine Dokumente subtrahieren, clientTopwenn das Dokument keinen Rand hat (normalerweise nicht), sodass Sie eine Position relativ zum Dokument haben
  • Subtrahieren element.clientTopSie, wenn Sie den Elementrand nicht als Teil des Elements betrachten
Jan Turoň
quelle
Element.getBoundingClientRect()gibt Positionen relativ zum Ansichtsfenster , nicht zum Dokument
Klaus
@Klaus: könntest du erklären was genau der Unterschied ist?
Jan Turoň
2
@ JanTuroň: Der Unterschied besteht darin, dass es relativ zum oberen Rand des Browserfensters ist, nicht zu den Dokumenten "true top". Dies bedeutet, dass negative Werte zurückgegeben werden, wenn Sie beispielsweise über den oberen Rand des Fensters scrollen.
Ryan Badour
5

Versuche dies: parseInt(jQuery.offset().top, 10)

Steve Chan
quelle
Ich wünschte, es gäbe einen Grund dafür, damit ich dich abstimmen könnte
Kick Buttowski
2

Es ist möglich, dass das offseteine nicht ganze Zahl sein kann, die emals Maßeinheit verwendet wird, relativ font-sizesin %.

Ich theoretisiere auch, dass dies offsetmöglicherweise keine ganze Zahl ist, wenn dies nicht der Fall zoomist, 100%aber das hängt davon ab, wie der Browser mit der Skalierung umgeht.

Emyr
quelle
2
Wenn der Zoom nicht 100% beträgt, gibt Ihnen offset (). top eine Vielzahl weiterer Probleme ... bugs.jquery.com/ticket/8362
commonpike
-1

Sie können verwenden parseInt(jQuery.offset().top), um den intWert Integer (primitiv - ) in allen Browsern immer zu verwenden.

ShankarSangoli
quelle
1
Verdoppelt oder schneidet parseInt () round sie ab?
Explosion Pills
Es wird nur der ganzzahlige Teil der Zahl verwendet und ist für alle Browser gleich.
ShankarSangoli
Das OP gibt an, dass es in einem Browser 327,5 gibt, während es in einem anderen 328 gibt. Wenn Sie also nur den ganzzahligen Teil (abgeschnitten) nehmen, ist das OP selbst ein Beispiel dafür, dass es nicht in allen Browsern gleich ist. Zumindest für dieses Beispiel müsste es gerundet werden, damit beide die gleiche Zahl erhalten.
Jimbo Jonny