Pase los eventos del mouse a través de un elemento ubicado

307

Estoy tratando de capturar eventos del mouse en un elemento con otro elemento absolutamente posicionado encima.

En este momento, los eventos en el elemento en una posición absoluta lo golpean y burbujean hasta su padre, pero quiero que sea "transparente" para estos eventos del mouse y reenviarlos a lo que esté detrás de él. ¿Cómo debo implementar esto?

s4y
fuente

Respuestas:

488
pointer-events: none;

Es una propiedad CSS que hace que los eventos "pasen" por el elemento al que se aplica y hace que el evento ocurra en el elemento "debajo".

Ver para más detalles: https://developer.mozilla.org/en/css/pointer-events

No es compatible hasta IE 11; todos los demás proveedores lo respaldan desde hace bastante tiempo (el soporte global fue de ~ 92% en 12 / '16): http://caniuse.com/#feat=pointer-events (gracias a @ s4y por proporcionar el enlace en los comentarios) .

JanD
fuente
3
¡Gracias! Esta es una solución perfecta para navegadores modernos (y no IE). En el momento en que se publicó esta pregunta, ¡no creo que pointer-eventsexistiera! Puedo cambiar la respuesta aceptada a esta en algún momento.
s4y
16
Woah, esto solo me salvó horas.
Dan Abramov
2
Acabo de cambiar la respuesta aceptada a esta. El soporte para pointer-events todavía no es súper impresionante , pero está mejorando. Para una opción más compatible, vaya con la respuesta de @ JedSchmidt.
s4y
1
Gracias, nunca supe que esto realmente existe. me salvó horas
Mohammed A. Al Jama
2
Pero, ¿qué sucede si solo desea dejar pasar algún evento como el evento de desplazamiento, pero que el elemento superior aún responda a todos los demás eventos? Establecer eventos de puntero en none mata todos los eventos en el elemento superior.
AndroidDev
50

Si todo lo que necesita es el mousedown, puede hacerlo con el document.elementFromPointmétodo de la siguiente manera:

  1. quitando la capa superior en mousedown,
  2. pasando las coordenadas xy ydel evento al document.elementFromPointmétodo para obtener el elemento debajo, y luego
  3. Restaurando la capa superior.
Jed Schmidt
fuente
99
Más explicaciones aquí: vinylfox.com/forwarding-mouse-events-through-layers
Nathan
2
Impresionante, ¡no sabía que ese método existía! También se puede utilizar con bastante facilidad para obtener todos los elementos objeto de cursor utilizando un tiempo de bucle para obtener el elemento de la cima y luego ocultarlo con el fin de encontrar la siguiente. Obtenga
jpeltoniemi
2
El problema con esta solución es que no funciona con el zoom de la página. Para dispositivos móviles o navegadores de escritorio con zoom en coordenadas XY ya no significan nada, y no hay una forma clara de calcular el zoom. Creo que para pellizcar el zoom es realmente imposible.
Impossibear
39

También es bueno saber ...
Los eventos de puntero se pueden deshabilitar para un elemento primario (probablemente div transparente) y, sin embargo, se pueden habilitar para elementos secundarios. Esto es útil si trabaja con varias capas div superpuestas, donde desea poder hacer clic en los elementos secundarios de cualquier capa. Para esto, todos los divs parenting obtienen pointer-events: noney click-children obtienen eventos de puntero reactivados porpointer-events: all

.parent {
    pointer-events:none;        
}
.child {
    pointer-events:all;
}

<div class="some-container">
   <ul class="layer-0 parent">
     <li class="click-me child"></li>
     <li class="click-me child"></li>
   </ul>

   <ul class="layer-1 parent">
     <li class="click-me-also child"></li>
     <li class="click-me-also child"></li>
   </ul>
</div>
Todo es uno
fuente
55
Impresionante, justo después de lo alto del descubrimiento pointer-events:noney la inminente decepción de tener niños afectados de nodos, salvas el día :)
Juan Cortés
;) muy contento por eso
Allisone
¿Se puede reducir a solo: .parent * { pointer-events:all; }para niños?
Dmitry
Debería ser "pointer-events: auto;". El valor "todos" se aplica solo a SVG. Ver developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
mattavatar
7

La razón por la que no está recibiendo el evento es porque el elemento en posición absoluta no es un elemento secundario del elemento que desea "hacer clic" (div azul). La forma más clara en la que puedo pensar es poner el elemento absoluto como hijo del que desea hacer clic, pero supongo que no puede hacer eso o no habría publicado esta pregunta aquí :)

Otra opción sería registrar un controlador de evento de clic para el elemento absoluto y llamar al controlador de clic para el div azul, haciendo que ambos parpadeen.

Debido a la forma en que los eventos surgen a través del DOM, no estoy seguro de que haya una respuesta más simple para ti, ¡pero tengo mucha curiosidad si alguien más tiene algún truco que no conozca!

Loktar
fuente
Gracias por la respuesta, Loktar. Desafortunadamente, en la página real no sabré qué hay debajo del elemento en posición absoluta, y puede haber más de un objetivo posible. La única solución que se me ocurre es tomar las coordenadas del mouse y compararlas con posibles objetivos para ver si se cruzan. Eso sería simplemente desagradable.
s4y
4

Hay una versión de JavaScript disponible que redirige manualmente los eventos de un div a otro.

Lo limpié y lo convertí en un complemento jQuery.

Aquí está el repositorio de Github: https://github.com/BaronVonSmeaton/jquery.forwardevents

Desafortunadamente, el propósito para el que lo estaba usando: la superposición de una máscara sobre Google Maps no capturó los eventos de clic y arrastre, y el cursor del mouse no cambia, lo que degrada la experiencia del usuario lo suficiente como para que decidiera ocultar la máscara debajo de IE y Opera. los dos navegadores que no admiten eventos de puntero.

Mikepote
fuente
1

Si conoce los elementos que necesitan eventos del mouse, y si su superposición es transparente, puede establecer el índice z de ellos en algo más alto que la superposición. Por supuesto, todos los eventos deberían funcionar en ese caso en todos los navegadores.

ricosrealm
fuente