Наведите курсор на элемент под курсором мыши при прокрутке - PullRequest
0 голосов
/ 05 июня 2018

Можно определить элемент под курсором мыши (т. Е. Самый верхний элемент) с помощью следующих методов:

  • Прослушивание события mousemove.Цель:
    • event.target или
    • document.elementFromPoint(event.clientX, event.clientY).

Это не работает при прокрутке пока мышь не двигается .Тогда мышь технически не двигается;таким образом, ни одно событие мыши не сработает.

К сожалению, оба метода, описанных выше, больше не применимы при прослушивании события scroll.event.target будет в зависимости от того, какой элемент прокручивается (или document).Кроме того, позиция курсора мыши не отображается на объекте event.

Как описано в , этот ответ на «Определите, какой элемент находится над указателем мыши в Javascript» , одинВозможным решением является запрос элемента hovered через псевдокласс CSS :hover.

document.addEventListener('scroll', () => {
  const hoverTarget = document.querySelector('.element:hover');
  if (hoverTarget) {
    hover(hoverTarget);
  }
});

Однако это невозможно использовать, поскольку он очень неэффективен и неточен.Событие scroll является одним из быстро запускаемых событий и должно быть замедлено при выполнении чего-либо незначительно дорогостоящего (например, запрос DOM).

Кроме того, элемент hovered отстает от , когдапрокрутки.Вы можете наблюдать это на любом веб-сайте с большим количеством ссылок: Наведите указатель мыши на одну из них и перейдите к другой ссылке, не перемещая мышь.Он обновляется только через несколько миллисекунд.

Есть ли способ, который может быть реализован красиво и эффективно?По сути, я хочу получить обратное значение mouseenter: вместо того, чтобы знать, когда мышь входит и элемент, я хочу знать, когда элемент пересекается с мышью (например, когда мышь не перемещается, а элемент [т.е. при прокрутке]).

1 Ответ

0 голосов
/ 05 июня 2018

Один из подходов к решению этой проблемы - сохранение местоположения курсора мыши с событием mousemove, а в событии scroll используйте document.elementFromPoint(x, y), чтобы определить элемент, который должен быть наведен.

Имейте в видучто это все еще довольно неэффективно из-за того, что событие scroll запускается с такой высокой частотой.Обработчик события должен иметь значение debounce , чтобы ограничить выполнение функции одним разом за задержку.Дэвид Уолш (David Walsh) объясняет, как это сделать в функции JavaScript Debounce .

let hoveredElement;
let mouseX = 0, mouseY = 0;

document.addEventListener('DOMContentLoaded', () => {
  document.addEventListener('mousemove', event => {
    mouseX = event.clientX;
    mouseY = event.clientY;

    hover(event.target);
  });

  document.addEventListener('scroll', () => {
    const hoverTarget = document.elementFromPoint(mouseX, mouseY);
    if (hoverTarget) {
      hover(hoverTarget);
    }
  });
});

function hover(targetElement) {
  // If the target and stored element are the same, return early
  // because setting it again is unnecessary.
  if (hoveredElement === targetElement) {
    return;
  }

  // On first run, `hoveredElement` is undefined.
  if (hoveredElement) {
    hoveredElement.classList.remove('hover');
  }

  hoveredElement = targetElement;
  hoveredElement.classList.add('hover');
}
.element {
  height: 200px;
  border: 2px solid tomato;
}

.element.hover {
  background-color: lavender;
}
<div class="container">
  <div class="element element-1">1</div>
  <div class="element element-2">2</div>
  <div class="element element-3">3</div>
  <div class="element element-4">4</div>
  <div class="element element-5">5</div>
</div>

В настоящее время решение наводит самый верхний элемент под мышью как при перемещении мыши, так и при прокрутке.Для вас может быть более подходящим присоединить прослушиватель mousemove к набору определенных элементов, а затем всегда указывать event.currentTarget (т. Е. Элемент, к которому подключен прослушиватель событий).Что касается части scroll, вы можете использовать hoverTarget.closest, чтобы найти подходящий элемент в дереве DOM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...