Передайте події миші через абсолютно розташований елемент


307

Я намагаюся фіксувати події миші на елементі з іншим абсолютно розташованим елементом поверх нього.

Зараз події на абсолютно розміщеному елементі потрапляють на нього і піднімаються до його батьківського, але я хочу, щоб він був "прозорим" для цих подій миші і пересилав їх до того, що стоїть за ним. Як я повинен це здійснити?

Відповіді:


489
pointer-events: none;

Це властивість CSS, яка змушує події "проходити" через елемент, до якого він застосований, і змушує подію відбуватися на елементі "внизу".

Докладні відомості див. На веб-сторінці : https://developer.mozilla.org/en/css/pointer-events

Не підтримується до IE 11; всі інші постачальники підтримують його з досить тривалого часу (глобальна підтримка становила ~ 92% за 12 / '16): http://caniuse.com/#feat=pointer-events (завдяки @ s4y за надання посилання в коментарях) .


3
Дякую! Це ідеальне рішення для сучасних браузерів (і не є IE). У той час, коли це питання було розміщено, я не думаю, що pointer-eventsіснувало! Я можу в якийсь момент переключити прийняту відповідь на цю.
s4y

16
О, це просто врятувало мені години.
Дан Абрамов

2
Я просто переключив прийняту відповідь на цю. Підтримка pointer-events досі не є надзвичайною , але вона стає кращою. Для більш сумісного варіанту перейдіть з відповіддю @ JedSchmidt.
s4y

1
Дякую, я ніколи не знав, що це насправді існує. це врятувало мені години
Мохаммед А. Аль-Джама

2
Але що робити, якщо ви просто хочете пропустити якусь подію, наприклад подію прокрутки, але верхній елемент все-таки відповість на всі інші події. Якщо встановити покажчик-події жодним чином, не вбиваються всі події на верхньому елементі.
AndroidDev

50

Якщо все, що вам потрібно, це мусульмане, ви, можливо, зможете зробити це за document.elementFromPointдопомогою:

  1. видалення верхнього шару на мусоні,
  2. передаючи xі yкоординати від події до document.elementFromPointметоду, щоб отримати елемент під ним, а потім
  3. відновлення верхнього шару.

9
Більш багатослівне пояснення тут: vinylfox.com/forwarding-mouse-events-through-layers
Натан

2
Дивовижно, я не знав, що такий метод навіть існує! Він може бути також використаний досить легко отримати всі елементи під курсором , використовуючи той час як цикл , щоб отримати верхній елемент , а потім приховати його, щоб знайти наступну. Захопіть мою версію тут: gist.github.com/Pichan/5498404
jpeltoniemi

2
Проблема цього вирішення полягає в тому, що він не працює з масштабуванням сторінки. Для мобільних пристроїв або настільних браузерів, які збільшують координати XY, більше нічого не означає, і немає чіткого способу розрахунку масштабу. я вважаю, що масштабування масштабу - це насправді неможливо.
Impossibear

39

Також приємно знати ...
Покажчики-події можуть бути відключені для батьківського елемента (можливо, прозорого div) та все ж увімкнено для дочірніх елементів. Це корисно, якщо ви працюєте з кількома перекриваються шарами Div, де ви хочете мати можливість натискати на дочірні елементи будь-якого шару. Для цього всі батьківські діви отримують, pointer-events: noneа діти-кліки отримують вказівники подій, які можна повторно активуватиpointer-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
Дивовижно, одразу після найвищого виявлення pointer-events:noneта неминучого виходу із дітей, які постраждали від вузлів, ви врятуєте день :)
Juan Cortés

;) Дуже ради з цього приводу
Allisone

Чи можна її звести до просто: .parent * { pointer-events:all; }для дітей?
Дмитро

Це має бути "pointer-events: auto;". Значення "всі" стосується лише SVG. Дивіться developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
mattavatar

7

Причина, коли ви не отримуєте подію, полягає в тому, що абсолютно розміщений елемент не є дочірньою частиною елемента, який ви хочете "натиснути" (синій div). Найчистіший спосіб, який я можу придумати, - це поставити абсолютним елементом як дочірній той, на кого ти хочеш натиснути, але я припускаю, що ти цього не можеш зробити, або ти б не написав тут це питання :)

Іншим варіантом було б зареєструвати обробник подій клацання для абсолютного елемента та викликати обробник клацання для синього дива, внаслідок чого вони обоє спалахнуть.

Через те, як події піднімаються через DOM, я не впевнений, що для вас є простіша відповідь, але мені дуже цікаво, якщо хтось ще має якісь хитрощі, про які я не знаю!


Дякую за відповідь, Локтаре. На жаль, на реальній сторінці я не буду знати, що знаходиться під абсолютно розміщеним елементом, і може бути більше однієї можливої ​​цілі. Єдине вирішення, про яке я можу придумати, - це захоплення координат миші та порівняння їх з можливими цілями, щоб побачити, чи перетинаються вони. Це було б просто неприємно.
s4y

4

Існує версія javascript, яка вручну перенаправляє події з одного діва на інший.

Я очистив його та перетворив його у плагін jQuery.

Ось сховище Github: https://github.com/BaronVonSmeaton/jquery.forwardevents

На жаль, мета, для якої я його використовував - накладення маски на Google Maps, не фіксувала події клацання та перетягування, а курсор миші не змінюється, що погіршує досвід користувача, щоб я просто вирішив приховати маску під IE і Opera - два браузери, які не підтримують події вказівника.


1

Якщо ви знаєте елементи, які потребують подій миші, і якщо ваше накладення прозоре, ви можете просто встановити z-індекс їх на щось вище, ніж накладання. Звичайно, всі події повинні працювати в цьому випадку на всіх браузерах.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.