2014-09-02 7 views
37

Ich möchte den genauen Abstand zwischen der Y-Koordinate eines Elements und dem Y-Wert = 0 haben, die ich als Anfang des Dokuments betrachte.JavaScript getBoundingClientRect() ändert sich beim Scrollen

Aber der Wert von getBoundingClientRect() scheint sich beim Scrollen zu ändern. Wie kann ich den tatsächlichen Abstand zwischen myElement und der Y-Koordinate = 0 (Anfang des Dokuments) erhalten?

+0

Ich würde wahrscheinlich als ein Betrüger von [Diese Frage] (http://stackoverflow.com/questions/442404/retrieve-the-position-xy-of-an-html-element) schließen, aber warum verwenden Sie 'getBoundingClientRect' und keine der üblichen Möglichkeiten, die Offset-Position relativ zum Dokument zu erhalten? – adeneo

+0

@adeneo Welche anderen Möglichkeiten gibt es? – enzian

+0

Sehen Sie sich die obige Frage an, oder sehen Sie sich an, was jQuery in 'offset' macht. – adeneo

Antwort

61

Es ist, weil getBoundingClientRect() erhält Werte in Bezug auf die window (nur der aktuelle sichtbare Teil der Seite), nicht die document (ganze Seite).
Daher ist es berücksichtigt auch Scrollen, wenn ihre Werte
Berechnung Grundsätzlich document = window + scroll

So die Entfernung zwischen myElement zu erhalten und die Y-Koordinate = 0 (Anfang des Dokuments), würden Sie hinzufügen auch Wert von vertikalen Scroll:

myElement.getBoundingClientRect().top + window.scrollY;

Quelle: https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect

+2

Ihre Lösung ist für Android Chrome 43 kaputt, und ich denke kaputt, wenn Sie im Internet Explorer Pinch-Zoom verwenden (mein Update wurde vor langer Zeit gemacht, um eine zu beheben Problem, es auf Ihre Art zu tun). – robocat

21

getBoundingClientRect ein bisschen mehr Pflege braucht zu vermeiden Fehler in Scrolly/pageYOffset:

function absolutePosition(el) { 
    var 
     found, 
     left = 0, 
     top = 0, 
     width = 0, 
     height = 0, 
     offsetBase = absolutePosition.offsetBase; 
    if (!offsetBase && document.body) { 
     offsetBase = absolutePosition.offsetBase = document.createElement('div'); 
     offsetBase.style.cssText = 'position:absolute;left:0;top:0'; 
     document.body.appendChild(offsetBase); 
    } 
    if (el && el.ownerDocument === document && 'getBoundingClientRect' in el && offsetBase) { 
     var boundingRect = el.getBoundingClientRect(); 
     var baseRect = offsetBase.getBoundingClientRect(); 
     found = true; 
     left = boundingRect.left - baseRect.left; 
     top = boundingRect.top - baseRect.top; 
     width = boundingRect.right - boundingRect.left; 
     height = boundingRect.bottom - boundingRect.top; 
    } 
    return { 
     found: found, 
     left: left, 
     top: top, 
     width: width, 
     height: height, 
     right: left + width, 
     bottom: top + height 
    }; 
} 

Die Fehler sind zu vermeiden:

  • in Android Chrome Scrollen seit 43 Chrome Mobil wrong values für Scrolly/pageYOffset hat (vor allem, wenn die Tastatur angezeigt wird und Sie scrollen).

  • Prise-Zoom in Microsoft IE oder Edge verursacht wrong values für scrollY/pageYOffset.

  • Einige (veraltete) Browser haben keine Höhe/Breite z. IE8

Edit: Der obige Code kann nur mit document.body.getBoundingClientRect() anstelle des Hinzufügens eines div viel vereinfacht werden - ich habe es nicht versucht aber so verlasse ich meine Antwort, wie es steht. Auch der Körper braucht margin:0 (reset.css tut dies normalerweise). This answer vereinfacht den Code erheblich, während die Fehler in jQuery.offset() vermieden werden!

+1

Perfekte Antwort. In meinem Fall hat der document.body.getBoundingClientRect() falsche Werte zurückgegeben, aber diese Antwort hat funktioniert. – ananda

Verwandte Themen