Passa gli eventi del mouse attraverso l'elemento assolutamente posizionato


307

Sto tentando di catturare eventi del mouse su un elemento con un altro elemento assolutamente posizionato sopra di esso.

In questo momento, gli eventi sull'elemento assolutamente posizionato lo colpiscono e si gonfiano verso il suo genitore, ma voglio che sia "trasparente" a questi eventi del mouse e li inoltri a tutto ciò che c'è dietro. Come dovrei implementarlo?

Risposte:


488
pointer-events: none;

È una proprietà CSS che fa "passare" gli eventi all'elemento a cui viene applicato e fa sì che l'evento si verifichi sull'elemento "sotto".

Per i dettagli, consultare: https://developer.mozilla.org/en/css/pointer-events

Non è supportato fino a IE 11; tutti gli altri fornitori lo supportano da un po 'di tempo (il supporto globale era ~ 92% in 12 / '16): http://caniuse.com/#feat=pointer-events (grazie a @ s4y per aver fornito il link nei commenti) .


3
Grazie! Questa è una soluzione perfetta per i browser moderni (e non IE). Al momento in cui questa domanda è stata pubblicata, non credo pointer-eventsesistesse! Potrei passare la risposta accettata a questa a un certo punto.
s4y,

16
Woah, questo mi ha appena salvato ore.
Dan Abramov,

2
Ho appena cambiato la risposta accettata a questa. Il supporto per pointer-events ancora non è eccezionale , ma sta migliorando. Per un'opzione più compatibile, vai con la risposta di @ JedSchmidt.
s4y,

1
Grazie, non ho mai saputo che esistesse davvero. mi ha risparmiato ore
Mohammed A. Al Jama

2
Ma cosa succede se si desidera solo far passare un evento come l'evento scroll, ma l'elemento superiore deve ancora rispondere a tutti gli altri eventi. L'impostazione di eventi del puntatore su nessuno uccide tutti gli eventi sull'elemento superiore.
AndroidDev

50

Se tutto ciò di cui hai bisogno è mousedown, potresti essere in grado di accontentarti del document.elementFromPointmetodo:

  1. rimuovere lo strato superiore su mousedown,
  2. passando le coordinate xe ydall'evento aldocument.elementFromPoint metodo per ottenere l'elemento sottostante e quindi
  3. ripristinare lo strato superiore.

9
Spiegazione più prolifica
Nathan

2
Fantastico, non sapevo nemmeno che quel metodo esistesse! Può anche essere usato abbastanza facilmente per mettere tutti gli elementi sotto il cursore usando un ciclo while per ottenere l'elemento più in alto e quindi nasconderlo per trovare quello successivo. Prendi la mia versione qui: gist.github.com/Pichan/5498404
jpeltoniemi,

2
Il problema con questa soluzione alternativa è che non funziona con lo zoom della pagina. Per i dispositivi mobili o i browser desktop ingranditi le coordinate XY non significano più nulla e non esiste un modo chiaro per calcolare lo zoom. credo che lo zoom con il pizzico sia effettivamente impossibile.
Impossibear,

39

Anche bello sapere ...
Gli eventi puntatore possono essere disabilitati per un elemento genitore (probabilmente div trasparente) e tuttavia essere abilitati per gli elementi figlio. Questo è utile se lavori con più div layer sovrapposti, in cui vuoi poter fare clic sugli elementi figlio di qualsiasi layer. Per questo tutti i div parenting ottengono pointer-events: nonee click-children ottengono riattivati ​​eventi puntatorepointer-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>

5
Fantastico, subito dopo il massimo della scoperta pointer-events:nonee l'imminente delusione di avere i nodi dei bambini colpiti, salvi il giorno :)
Juan Cortés,

;) molto contento di questo
Allisone il

Può essere ridotto a solo: .parent * { pointer-events:all; }per i bambini?
Dmitry

Dovrebbe essere "pointer-events: auto;". Il valore "tutto" si applica solo agli SVG. Vedi developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
mattavatar,

7

Il motivo per cui non si riceve l'evento è perché l'elemento posizionato in modo assoluto non è figlio dell'elemento che si desidera "fare clic" (div blu). Il modo più pulito a cui riesco a pensare è quello di mettere l'elemento assoluto come figlio di quello su cui vuoi fare clic, ma suppongo che non puoi farlo o non avresti pubblicato questa domanda qui :)

Un'altra opzione sarebbe quella di registrare un gestore di eventi click per l'elemento assoluto e chiamare il gestore click per il div blu, facendo lampeggiare entrambi.

A causa del modo in cui gli eventi si diffondono nel DOM, non sono sicuro che ci sia una risposta più semplice per te, ma sono molto curioso di sapere se qualcun altro ha qualche trucco che non conosco!


Grazie per la risposta, Loktar. Sfortunatamente, sulla pagina reale non saprò cosa c'è sotto l'elemento assolutamente posizionato e potrebbe esserci più di un possibile target. L'unica soluzione che mi viene in mente è di afferrare le coordinate del mouse e confrontarle con possibili obiettivi per vedere se si intersecano. Sarebbe semplicemente brutto.
s4y,

4

È disponibile una versione javascript che reindirizza manualmente gli eventi da un div all'altro.

L'ho pulito e trasformato in un plugin jQuery.

Ecco il repository Github: https://github.com/BaronVonSmeaton/jquery.forwardevents

Sfortunatamente, lo scopo per cui lo stavo usando - sovrapporre una maschera su Google Maps non ha catturato eventi di clic e trascinamento, e il cursore del mouse non cambia, il che degrada l'esperienza dell'utente abbastanza che ho appena deciso di nascondere la maschera in IE e Opera - i due browser che non supportano gli eventi puntatore.


1

Se conosci gli elementi che richiedono eventi del mouse e se la tua sovrapposizione è trasparente, puoi semplicemente impostare il loro indice z su qualcosa di più alto della sovrapposizione. Tutti gli eventi dovrebbero ovviamente funzionare in quel caso su tutti i browser.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.