2010-02-25 19 views
21

Dada la posición absoluta o relativa (arriba & izquierda) ¿hay alguna forma de obtener el elemento html más cercano a estas coordenadas?Buscar el elemento html más cercano a la posición (relativo o absoluto)

O, alternativamente, ¿hay alguna forma de crear un selector (o usar alguna construcción jQuery) para enumerar elementos y luego buscar cuál se cierra a las coordenadas proporcionadas? Supongamos que el conjunto de elementos es pequeño y finito.

+0

¿También hago la suposición de que usted determina "más cercano" como la parte superior/izquierda más cercana? ¿Qué pasa con un elemento dentro de un elemento? Si está contenido, ¿está "más cerca" de su padre? –

+0

este es un conjunto predefinido de elementos, y una lista plana así que afortunadamente no es tan complejo como en otros casos. Lo más cercano es en términos de compensación superior/izquierda. – psychotik

Respuesta

20

he construido un método jQuery que devuelve el elemento más cercano a compensar, dentro de la colección:

jQuery.fn.closestToOffset = function(offset) { 
    var el = null, 
     elOffset, 
     x = offset.left, 
     y = offset.top, 
     distance, 
     dx, 
     dy, 
     minDistance; 
    this.each(function() { 
     var $t = $(this); 
     elOffset = $t.offset(); 
     right = elOffset.left + $t.width(); 
     bottom = elOffset.top + $t.height(); 

     if (
      x >= elOffset.left && 
      x <= right && 
      y >= elOffset.top && 
      y <= bottom 
     ) { 
      el = $t; 
      return false; 
     } 

     var offsets = [ 
      [elOffset.left, elOffset.top], 
      [right, elOffset.top], 
      [elOffset.left, bottom], 
      [right, bottom], 
     ]; 
     for (var off in offsets) { 
      dx = offsets[off][0] - x; 
      dy = offsets[off][1] - y; 
      distance = Math.sqrt(dx * dx + dy * dy); 
      if (minDistance === undefined || distance < minDistance) { 
       minDistance = distance; 
       el = $t; 
      } 
     } 
    }); 
    return el; 
}; 

Notas:

  1. Si el desplazamiento es dentro de uno de los elementos, se devolverá.
  2. Estoy recorriendo cuatro desfases, porque esto proporciona la mejor precisión.

utilizar de esta manera:

$('div.myCollection').closestToOffset({left: 5, top: 5}); 
+0

Tengo curiosidad por saber cómo es el rendimiento si tienes muchos elementos (como miles). – pixelfreak

+1

Estoy usando esta función y funciona bien, incluso con muchos elementos. Debería ser O (n). Y, de todos modos, no creo que puedas reducir el tiempo total, así que solo intenta ver si funciona para ti. – Sagi

+0

Si div.myCollection contiene elementos anidados, es posible que desee seguir buscando hasta que encuentre el elemento más interno en el que se encuentra el punto. Document.elementFromPoint() también podría ser un buen lugar para comenzar. –

1

Lo mejor que puedo hacer es tener un bucle de función de búsqueda que recorre todos los elementos existentes y compara las coordenadas, manteniendo una copia de la variable más cercana todo el tiempo.

Esa es la forma en que puedo pensar en hacer esto, y lo que haría si estuviera bajo sus limitaciones.

+0

gracias ... eso es lo que creo/sé que funcionará, pero definitivamente preferiría que otra solución fuera posible. – psychotik

+1

@psychotik: Solo asegúrate de no medir las dimensiones de los elementos en el ciclo. Cada medida activa un reflujo del navegador. Simplemente 'arriba' y 'izquierda' está bien, creo. –

1

bucle a través de todos los elementos es bastante fácil:

function getClosestElement(x, y) { 
    var elements, el, offset, dist, i, minDist, closestEl; 

    elements = $("body *"); 
    closestEl = elements.eq(i); 
    offset = closestEl.offset(); 
    offset.left += el.outerWidth()/2; // center of object 
    offset.top += el.outerHeight()/2; // middle of object 
    minDist = Math.sqrt((offset.left - x)*(offset.left - x) + (offset.top - y)*(offset.top - y)); 

    for (var i=0; i < elements.length; i++) { 
     el = elements.eq(i); 
     offset = el.offset(); 
     offset.left += el.outerWidth()/2; // center of object 
     offset.top += el.outerHeight()/2; // middle of object 
     dist = Math.sqrt((offset.left - x)*(offset.left - x) + (offset.top - y)*(offset.top - y)); 
     if (dist < minDist) { 
      minDist = dist; 
      closestEl = el; 
     } 
    } 

    return closestEl; 
+1

¿Por qué esta respuesta plagada de errores se ha permitido que se siente aquí durante cinco años, listo para molestar al próximo fanático que venga, no tengo idea. – HeyHeyJC

-1

o tratar de la función original de jQuery offsetparent(). De esta página viene el siguiente ejemplo:

$("li.item-a").offsetParent().css("background-color", "red"); 
+0

Más cercano a la posición, no en DOM – koMah

Cuestiones relacionadas