offsetTop frente a jQuery.offset (). top

82

He leído eso offsetLefty offsetTopno funciona correctamente en todos los navegadores. jQuery.offset()se supone que proporciona una abstracción para que esto proporcione el valor correcto xbrowser.

Lo que estoy tratando de hacer es obtener las coordenadas de donde se hizo clic en un elemento en relación con la parte superior izquierda del elemento.

El problema es que en jQuery.offset().toprealidad me está dando un valor decimal en FFX 3.6 (en IE y Chrome, los dos valores coinciden).

Este violín muestra el problema. Si hace clic en la imagen inferior, jQuery.offset().topdevuelve 327.5, pero offsetTopdevuelve 328.

Me gustaría pensar que offset()está devolviendo el valor correcto y debería usarlo porque funcionará en todos los navegadores. Sin embargo, la gente obviamente no puede hacer clic en decimales de píxeles. ¿Es la forma correcta de determinar el verdadero desplazamiento al Math.round()desplazamiento que devuelve jQuery? ¿Debería usar offsetTopen su lugar, o algún otro método por completo?

Pastillas de explosión
fuente

Respuestas:

15

Creo que tiene razón al decir que las personas no pueden hacer clic en medios píxeles, por lo que personalmente, usaría el desplazamiento jQuery redondeado ...

ChristopheCVB
fuente
4
El desplazamiento de jQuery tiene errores cuando se usa el zoom CSS
Mladen Janjetovic
76

Esto es lo que dice jQuery API Doc sobre .offset():

Obtenga las coordenadas actuales del primer elemento, o establezca las coordenadas de cada elemento, en el conjunto de elementos coincidentes, en relación con el documento .

Esto es lo que dice MDN Web API sobre .offsetTop:

offsetTop devuelve la distancia del elemento actual en relación con la parte superior del nodo offsetParent

Esto es lo que .offset()básicamente hace jQuery v.1.11 al obtener las coordenadas:

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 intuitivamente dice cuánto se desplazó la página
  • docElem.scrollTop es el respaldo para IE <9 (que por cierto no son compatibles con jQuery 2)
  • docElem.clientTop es el ancho del borde superior de un elemento (el documento en este caso)
  • elem.getBoundingClientRect()obtiene las coordenadas relativas a la ventana gráfica del documento (ver comentarios). Puede devolver valores de fracción, por lo que esta es la fuente de su error. También puede causar un error en IE <8 cuando se amplía la página. Para evitar valores de fracción, intente calcular la posición de forma iterativa

Conclusión

  • Si desea coordenadas relativas al nodo principal , utilice element.offsetTop. Agregue element.scrollTopsi desea tener en cuenta el desplazamiento principal. (o use jQuery .position () si es fanático de esa biblioteca)
  • Si desea coordenadas relativas a la ventana gráfica, utilice element.getBoundingClientRect().top. Agregue window.pageYOffsetsi desea tener en cuenta el desplazamiento del documento. No es necesario restar el documento clientTopsi el documento no tiene borde (generalmente no lo tiene), por lo que tiene una posición relativa al documento
  • Reste element.clientTopsi no considera el borde del elemento como parte del elemento
Jan Turoň
fuente
Element.getBoundingClientRect()da posiciones relativas a la ventana gráfica , no al documento
Klaus
@Klaus: ¿podrías explicar cuál es exactamente la diferencia?
Jan Turoň
2
@ JanTuroň: La diferencia es que es relativa a la parte superior de la ventana del navegador, no a la "parte superior verdadera" de los documentos. Lo que significa que devolverá valores negativos si desplaza la parte superior más allá de la parte superior de la ventana, por ejemplo.
Ryan Badour
5

Prueba esto: parseInt(jQuery.offset().top, 10)

Steve Chan
fuente
Ojalá hubiera una razón detrás de esto, para poder votar por
ti
2

Es posible que offsetno sea un número entero, utilizando emcomo unidad de medida, relativo font-sizesen %.

También teorizo ​​que offsetpuede que no sea un número entero cuando zoomno lo es, 100%pero eso depende de cómo maneja el navegador la escala.

Emyr
fuente
2
si el zoom no es del 100%, offset (). top le dará una gran cantidad de otros problemas ... bugs.jquery.com/ticket/8362
commonpike
-1

Puede usar parseInt(jQuery.offset().top)para usar siempre el valor Integer (primitivo - int) en todos los navegadores.

ShankarSangoli
fuente
1
¿ParseInt () round los duplica o los trunca?
Píldoras
Solo tomará la parte entera del número y será el mismo en todos los navegadores.
ShankarSangoli
El OP establece que en un navegador da 327.5 mientras que en otro da 328. Entonces, si solo toma la parte entera (truncar), el OP en sí es un ejemplo de que no es el mismo en todos los navegadores. Para este ejemplo, al menos tendría que redondearse para que ambos den el mismo número.
Jimbo Jonny