2011-03-28 8 views
5

Estoy tratando de obtener las coordenadas de un elemento en una página. He estado usando la forma estándar para obtenerlo:Obtiene compensación real izquierda/parte superior del elemento con compensador en línea

var el = element, pos = {x: 0, y: 0}; 
while (el) { 
    pos.x += el.offsetLeft; 
    pos.y += el.offsetTop; 
    el = el.offsetParent; 
} 

Pero este método falla cuando el elemento en cuestión tiene display: block, y uno de los offsetParents tiene display: inline;. Esto es debido al hecho descrito en this thread:

The element starts in the middle of the text

Después de algún tratando con jQuery resulta que su .offset() -method devuelve el correcto desplazamiento, y yo he mirado a través de la fuente pero no se encuentra exactamente cómo ellos lo hacen. Entonces mi pregunta es: ¿cómo obtengo la posición exacta? No puedo usar jQuery para este proyecto, y el método en the thread described earlier es engorroso, agregar un elemento y probar es demasiado trabajo (perspectiva de rendimiento) y tampoco está disponible el uso de Element.getBoundingClientRect.

Si tienes ganas de probarlo se puede ir a Apple.com abrir el depurador de elección y escriba lo siguiente:

var el, el2; 
el = el2 = document.querySelector('#worldwide span'); 
var pos = {x: 0, y: 0}; 
while (el2) { 
    pos.x += el2.offsetLeft; 
    pos.y += el2.offsetTop; 
    el2 = el2.offsetParent; 
} 
alert("Calculated position: " + pos.x + "x" + pos.y + " window size: " + screen.width + "x" + screen.height); 

Con este código me sale:. Calculated position: 1354x988 window size: 1280x800 (es decir, el desplazamiento izquierda es la forma de la pantalla, que claramente no es)

¿Cómo es esto posible? ¿Alguna idea de trabajo? Aproximaciones? No tiene que ser exacto, pero tiene que ser mejor que antes. Gracias.

Editar: Esto es para el motor de renderizado WebKit, para aclarar.

Respuesta

2

Terminé yendo con WebKit's window.webkitConvertPointFromNodeToPage, pero seguí golpeando un error en el que devolvería una posición que era totalmente incorrecta. La investigación adicional reveló que si el nodo en cuestión se mostraba: en línea, devolvería la posición del último elemento de bloque en la jerarquía.

La búsqueda de una resolución para esta imagen no resultó nada (todo lo que encontré fue información muy básica sobre lo que realmente hizo webkitConvertPointFromNodeToPage y el código fuente de WebKit).

Supongo que descubrí que devolvía la posición correcta si el elemento tenía display: inline-block, por lo que si el elemento estaba en línea, lo cambié a bloque en línea y luego calculé la posición.

Si alguien tiene una mejor solución para este problema, me gustaría saber de usted!

Editar:

Resulta que el cambio de estilo de visualización de inline-block no es siempre una buena idea, así que en vez de hacer que estoy usando este método:

var offset = {x: 0, y: 0}; 
if (getStyle(el, 'display') == 'inline') { 
    offset.x = el.offsetLeft - el.parentNode.offsetLeft; 
    offset.y = el.offsetTop - el.parentNode.offsetTop; 
} 

var point = window.webkitConvertPointFromNodeToPage(el, new WebKitPoint(0, 0)); 

return { 
    x: Math.round(point.x + offset.x), 
    y: Math.round(point.y + offset.y) 
} 

estoy tomando el offset del niño en línea Top/Izquierda y restando eso de su padre. No estoy muy seguro de cómo funciona en los padres que tienen pantalla: en línea, pero funciona el 90% del tiempo.

Pero si alguien tiene una idea mejor todavía estoy abierto para sugerencias.

1

Probablemente here usted encontrará la descripción de las ideas usadas en the source code of jQuery.offset.

Si mira here, puede ver que offsetLeft y offsetTop no funcionan del todo en las versiones anteriores de IE.

Entiendo que es interesante comprender cómo se puede implementar esta u otras cosas. Cómo se ve el código fuente de la función jQuery.offset no es tan fácil. Si desea que su código funcione correctamente y sea independiente del navegador, debería usar simplemente jQuery.offset en lugar de escribir su propia implementación.

1

El examen del código fuente webConvertPointFromNodeToPage revela que se calcula utilizando el objeto de renderizado del elemento, y si no existe dicho representador, utiliza el antecesor neareset que tiene un renderizador. Sin embargo, cuando se utiliza un renderizador ancestro, no ajusta el desplazamiento para tener en cuenta la diferencia de origen entre el objetivo y el origen de su antepasado. Esto significa que la función funciona correctamente cuando el punto se da en relación con el renderizador que lo contiene. Si el elemento para el que está calculando las coordenadas no tiene un procesador, debe ajustar manualmente el desplazamiento al ancestro más cercano que sí lo tenga (utilizando offsetLeft/Top). Saber exactamente qué elementos tienen procesadores requeriría más investigación, pero generalmente cualquier elemento que no tenga contenido pero que afecte a la visualización de otros nodos, como SPAN, no necesita un procesador.

1

Tuve el mismo problema al usar $.offset().left con jQuery, tratando de obtener la posición de una palabra dentro de un párrafo.

El uso de $.offset().left dentro de una función $(document).ready() arrojó un resultado incorrecto.

El uso de $.offset().left en una función $(window).load() resolvió mi problema en WebKit.

Esto es particularmente relevante cuando puede haber elementos de imagen flotantes o fuentes que afectarán el diseño.

Cuestiones relacionadas