Przekazuj zdarzenia myszy przez element absolutnie umieszczony

307

Próbuję uchwycić zdarzenia myszy na elemencie z innym absolutnie pozycjonowanym elementem na nim.

W tej chwili zdarzenia na absolutnie pozycjonowanym elemencie uderzają w niego i podskakują do jego rodzica, ale chcę, aby był „przezroczysty” dla tych zdarzeń myszy i przekazywał je temu, co za nim stoi. Jak mam to zaimplementować?

s4y
źródło

Odpowiedzi:

489
pointer-events: none;

Jest właściwością CSS, która powoduje, że zdarzenia „przechodzą” przez element, do którego są stosowane, i sprawia, że ​​zdarzenie występuje w elemencie „poniżej”.

Zobacz szczegóły: https://developer.mozilla.org/en/css/pointer-events

Nie jest obsługiwany do IE 11; wszyscy inni dostawcy obsługują go od dłuższego czasu (globalne wsparcie wyniosło ~ 92% w 12 / '16): http://caniuse.com/#feat=pointer-events (dzięki @ s4y za udostępnienie linku w komentarzach) .

JanD
źródło
3
Dzięki! Jest to idealne rozwiązanie dla nowoczesnych (i nie-IE) przeglądarek. W chwili opublikowania tego pytania nie sądzę, by pointer-eventsistniało! W pewnym momencie mogę zmienić przyjętą odpowiedź na tę.
s4y
16
Woah, to tylko zaoszczędziło mi godziny.
Dan Abramov
2
Właśnie zmieniłem zaakceptowaną odpowiedź na tę. Obsługa pointer-events wciąż nie jest super , ale jest coraz lepsza. Aby uzyskać bardziej zgodną opcję, przejdź do odpowiedzi @ JedSchmidt.
s4y 18.12.12
1
Dzięki, nigdy nie wiedziałem, że to naprawdę istnieje. zaoszczędził mi wiele godzin
Mohammed A. Al Jama,
2
Ale co, jeśli chcesz pozwolić, aby jakieś zdarzenie, takie jak zdarzenie przewijania, przeszło, ale górny element nadal reaguje na wszystkie inne zdarzenia. Ustawienie none na wskaźnik-event zabija wszystkie zdarzenia na górnym elemencie.
AndroidDev,
50

Jeśli wszystko, czego potrzebujesz, to wycofanie się, możesz być w stanie zadowolić się tą document.elementFromPointmetodą przez:

  1. usunięcie górnej warstwy przy mousedown,
  2. przekazanie współrzędnych xi yze zdarzenia do document.elementFromPointmetody, aby uzyskać element pod spodem, a następnie
  3. przywracanie górnej warstwy.
Jed Schmidt
źródło
9
Bardziej mgliste wyjaśnienie tutaj: winylfox.com/forwarding-mouse-events-through-layers
Nathan
2
Wspaniale, nie wiedziałem, że ta metoda w ogóle istnieje! Można stosować również dość łatwo uzyskać wszystkie elementy pod kursorem za pomocą while pętli, aby uzyskać najwyższą element, a następnie ukryć je w celu znalezienia następnego. Złap moją wersję tutaj: gist.github.com/Pichan/5498404
jpeltoniemi
2
Problem z tym obejściem polega na tym, że nie działa on z powiększaniem strony. W przypadku urządzeń mobilnych lub przeglądarek komputerowych powiększonych współrzędnymi XY nic już nie znaczy i nie ma jasnego sposobu na obliczenie powiększenia. wierzę, że powiększenie szczypcami jest w rzeczywistości niemożliwe.
Impossibear
39

Również miło wiedzieć ...
Zdarzenia wskaźnika mogą być wyłączone dla elementu nadrzędnego (prawdopodobnie przezroczystej div), a jednak włączone dla elementów potomnych. Jest to przydatne, jeśli pracujesz z wieloma nakładającymi się warstwami div, w których chcesz móc klikać elementy potomne dowolnej warstwy. W tym celu wszystkie divy rodzicielskie otrzymują, pointer-events: nonea dzieci-kliknięcia otrzymują zdarzenia-wskaźnik ponownie włączone przezpointer-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>
Wszystko jest jednym
źródło
5
Niesamowite, zaraz po szczycie odkrywania pointer-events:nonei nieuchronnym rozczarowaniu spowodowanym dotknięciem węzłów dziecięcych, oszczędzasz dzień :)
Juan Cortés
;) bardzo się cieszę
Allisone,
Czy można to sprowadzić tylko do: .parent * { pointer-events:all; }dla dzieci?
Dmitry
Powinien to być „wskaźnik-zdarzenia: auto;”. Wartość „wszystko” dotyczy tylko plików SVG. Zobacz developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
mattavatar,
7

Powodem, dla którego nie otrzymujesz zdarzenia, jest to, że element pozycjonowany absolutnie nie jest dzieckiem elementu, który chcesz „kliknąć” (niebieski div). Najczystszym sposobem, jaki mogę wymyślić, jest umieszczenie absolutnego elementu jako dziecka tego, który chcesz kliknąć, ale zakładam, że nie możesz tego zrobić, bo nie opublikowałbyś tego pytania tutaj :)

Inną opcją byłoby zarejestrowanie modułu obsługi zdarzenia kliknięcia dla elementu absolutnego i wywołanie modułu obsługi kliknięcia dla niebieskiego elementu div, powodując, że oba będą migać.

Ze względu na sposób, w jaki wydarzenia pojawiają się w DOM, nie jestem pewien, czy istnieje dla ciebie prostsza odpowiedź, ale jestem bardzo ciekawy, czy ktoś ma jakieś sztuczki, o których nie wiem!

Loktar
źródło
Dzięki za odpowiedź, Loktar. Niestety, na prawdziwej stronie nie będę wiedział, co kryje się pod absolutnie pozycjonowanym elementem i może istnieć więcej niż jeden możliwy cel. Jedyne obejście, jakie mogę wymyślić, to chwytanie współrzędnych myszy i porównywanie ich z możliwymi celami, aby sprawdzić, czy się przecinają. To byłoby po prostu paskudne.
s4y
4

Dostępna jest wersja javascript, która ręcznie przekierowuje zdarzenia z jednego div na inny.

Wyczyściłem go i przekształciłem w wtyczkę jQuery.

Oto repozytorium Github: https://github.com/BaronVonSmeaton/jquery.forwardevents

Niestety cel, w którym go użyłem - nałożenie maski na Mapy Google nie uchwyciło zdarzeń kliknięcia i przeciągnięcia, a kursor myszy się nie zmienia, co obniża wrażenia użytkownika na tyle, że postanowiłem ukryć maskę pod IE i Operą - dwie przeglądarki, które nie obsługują zdarzeń wskaźnika.

Mikepote
źródło
1

Jeśli znasz elementy wymagające zdarzeń myszy, a twoja nakładka jest przezroczysta, możesz po prostu ustawić ich indeks Z na wartość wyższą niż nakładka. Wszystkie zdarzenia powinny oczywiście działać w tym przypadku we wszystkich przeglądarkach.

rikosrealizm
źródło