2014-09-02 26 views
37

Voglio avere la distanza esatta tra la coordinata Y di un elemento e il valore Y = 0, che considero come la parte superiore del documento.JavaScript getBoundingClientRect() cambia durante lo scorrimento

myElement.getBoundingClientRect().top; 

Ma il valore di getBoundingClientRect() sembra cambiare durante lo scorrimento. Come posso ottenere la distanza reale tra myElement e la coordinata Y = 0 (inizio del documento)?

+0

Probabilmente chiuderei come un duplicato di [Questa domanda] (http://stackoverflow.com/questions/442404/retrieve-the-position-xy-of-an-html-element), ma perché stai usando 'getBoundingClientRect' e non uno dei soliti modi per ottenere la posizione dell'offset rispetto al documento? – adeneo

+0

@adeneo Quali altri modi ci sono? – enzian

+0

Vedere la domanda sopra, o guardare a ciò che jQuery fa in 'offset' – adeneo

risposta

61

È perché ottiene valori rispetto allo window (solo la parte visibile corrente della pagina), non lo document (pagina intera).
Quindi, ci vuole anche scorrere nel calcolo dei suoi valori
Fondamentalmente, document = window + scroll

Quindi, per ottenere la distanza tra MyElement e la coordinata y = 0 (all'inizio della pagina), si avrebbe aggiungere la valore del verticale-scroll anche:

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

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

+2

La tua soluzione è rotta per Android Chrome 43, e penso che sia rotto se si utilizza lo zoom su Internet Explorer (la mia correzione è stata fatta molto tempo fa per risolvere un problema problema facendolo a modo tuo). – robocat

21

getBoundingClientRect ha bisogno di un po 'più di attenzione per evitare errori 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 
    }; 
} 

Gli insetti da evitare sono:

  • lo scorrimento in Android Chrome dal Chrome mobile 43 ha wrong values per scrolly/pageYOffset (soprattutto quando la tastiera viene visualizzata e si scorre).

  • Zoom pinch in Microsoft IE o Bordo causa wrong values per scrollY/pageYOffset.

  • Alcuni browser (obsoleti) non hanno altezza/larghezza, ad es. IE8

Edit: Il codice di cui sopra può essere semplificato molto da solo utilizzando document.body.getBoundingClientRect() invece di aggiungere un div - io non l'ho provato anche se così sto lasciando la mia risposta così com'è. Anche il corpo ha bisogno di margin:0 (reset.css di solito lo fa). This answer semplifica molto il codice, evitando comunque gli errori in jQuery.offset()!

+1

Risposta perfetta. Nel mio caso, document.body.getBoundingClientRect() ha restituito valori errati ma questa risposta ha funzionato. – ananda

Problemi correlati