Lewati acara mouse melalui elemen yang benar-benar diposisikan


307

Saya mencoba menangkap peristiwa mouse pada suatu elemen dengan elemen lain yang benar-benar diposisikan di atasnya.

Saat ini, peristiwa pada elemen yang benar-benar diposisikan memukul dan melambung ke induknya, tapi saya ingin itu menjadi "transparan" untuk peristiwa mouse ini dan meneruskannya ke apa pun yang ada di belakangnya. Bagaimana saya harus menerapkan ini?

Jawaban:


488
pointer-events: none;

Adalah properti CSS yang membuat acara "melewati" elemen yang diterapkan dan membuat acara terjadi pada elemen "di bawah".

Lihat detailnya: https://developer.mozilla.org/en/css/pointer-events

Tidak didukung hingga IE 11; semua vendor lain mendukungnya sejak beberapa waktu (dukungan global ~ 92% pada 12 / '16): http://caniuse.com/#feat=pointer-events (terima kasih kepada @ s4y karena menyediakan tautan dalam komentar) .


3
Terima kasih! Ini adalah solusi sempurna untuk browser modern (dan non-IE). Pada saat pertanyaan ini diposting, saya rasa tidak pointer-eventsada! Saya dapat mengalihkan jawaban yang diterima ke yang ini di beberapa titik.
s4y

16
Woah, ini baru menyelamatkan saya berjam-jam.
Dan Abramov

2
Saya baru saja mengganti jawaban yang diterima untuk yang ini. Dukungan untuk pointer-events masih tidak super luar biasa , tetapi semakin baik. Untuk opsi yang lebih kompatibel, buka dengan jawaban @ JedSchmidt.
s4y

1
Terima kasih, saya tidak pernah tahu ini benar-benar ada. itu menyelamatkan saya berjam
Mohammed A. Al Jama

2
Tetapi bagaimana jika Anda hanya ingin membiarkan beberapa acara seperti acara gulir untuk melewati tetapi untuk elemen atas untuk tetap menanggapi semua acara lainnya. Mengatur pointer-events ke none membunuh semua peristiwa pada elemen atas.
AndroidDev

50

Jika semua yang Anda butuhkan adalah mousedown, Anda mungkin dapat puas dengan document.elementFromPointmetode ini, dengan:

  1. menghapus lapisan atas pada mousedown,
  2. melewati xdan ykoordinat dari acara ke document.elementFromPointmetode untuk mendapatkan elemen di bawahnya, dan kemudian
  3. mengembalikan lapisan atas.

9
Penjelasan lebih bertele-tele di sini: vinylfox.com/forwarding-mouse-events-through-layers
Nathan

2
Luar biasa, saya tidak tahu metode itu ada! Dapat juga digunakan dengan cukup mudah untuk mendapatkan semua elemen di bawah kursor menggunakan loop sementara untuk mendapatkan elemen paling atas dan kemudian menyembunyikannya untuk menemukan yang berikutnya. Raih
jpeltoniemi

2
Masalah dengan penyelesaian ini adalah tidak berfungsi dengan memperbesar halaman. Untuk perangkat seluler atau browser desktop yang diperbesar dengan koordinat XY tidak lagi berarti apa-apa, dan tidak ada cara yang jelas untuk menghitung zoom. saya percaya untuk pinch zooming sebenarnya tidak mungkin.
Tidak mungkin

39

Juga menyenangkan untuk diketahui ...
Pointer-events dapat dinonaktifkan untuk elemen induk (mungkin transparan div) dan belum diaktifkan untuk elemen anak. Ini berguna jika Anda bekerja dengan beberapa lapisan div yang tumpang tindih, tempat Anda ingin dapat mengeklik elemen turunan dari lapisan apa pun. Untuk ini, semua parenting div dapatkan pointer-events: nonedan klik-anak-anak mendapatkan pointer-events diaktifkan kembali olehpointer-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
Luar biasa, tepat setelah penemuan yang tinggi pointer-events:nonedan penurunan yang cepat karena memiliki simpul anak-anak yang terpengaruh, Anda menyelamatkan hari itu :)
Juan Cortés

;) sangat senang tentang itu
Allisone

Bisakah itu direbus menjadi: .parent * { pointer-events:all; }untuk anak-anak?
Dmitry

Itu harus "pointer-events: auto;". Nilai "semua" hanya berlaku untuk SVG. Lihat developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
mattudad

7

Alasan Anda tidak menerima acara adalah karena elemen yang diposisikan benar-benar bukan anak dari elemen yang ingin Anda "klik" (blue div). Cara terbersih yang dapat saya pikirkan adalah dengan meletakkan elemen absolut sebagai anak dari yang Anda ingin klik, tapi saya berasumsi Anda tidak dapat melakukan itu atau Anda tidak akan mengirim pertanyaan ini di sini :)

Pilihan lain adalah mendaftarkan pengendali event klik untuk elemen absolut dan memanggil pengendali klik untuk div biru, menyebabkan keduanya flash.

Karena cara acara muncul melalui DOM, saya tidak yakin ada jawaban yang lebih sederhana untuk Anda, tetapi saya sangat ingin tahu apakah ada orang lain yang memiliki trik yang tidak saya ketahui!


Terima kasih atas tanggapannya, Loktar. Sayangnya, pada halaman sebenarnya saya tidak akan tahu apa yang ada di bawah elemen yang diposisikan sepenuhnya, dan mungkin ada lebih dari satu target yang mungkin. Satu-satunya solusi yang dapat saya pikirkan adalah meraih koordinat mouse dan membandingkannya dengan target yang mungkin untuk melihat apakah mereka berpotongan. Itu akan sangat tidak menyenangkan.
s4y

4

Ada versi javascript yang tersedia yang secara manual mengalihkan acara dari satu div ke yang lain.

Saya membersihkannya dan membuatnya menjadi plugin jQuery.

Inilah repositori Github: https://github.com/BaronVonSmeaton/jquery.forwardevents

Sayangnya, tujuan saya menggunakannya untuk - overlay topeng di Google Maps tidak menangkap peristiwa klik dan seret, dan kursor mouse tidak berubah yang menurunkan pengalaman pengguna yang cukup sehingga saya memutuskan untuk menyembunyikan topeng di bawah IE dan Opera - dua browser yang tidak mendukung acara pointer.


1

Jika Anda tahu elemen-elemen yang membutuhkan peristiwa mouse, dan jika overlay Anda transparan, Anda bisa mengatur z-index dari mereka ke sesuatu yang lebih tinggi daripada overlay. Semua acara tentunya harus bekerja dalam kasus itu di semua browser.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.