繁体   English   中英

滚动时将元素悬停在鼠标光标下方

[英]Hover the element below the mouse cursor when scrolling

可以使用以下技术确定鼠标光标下方的元素(即最顶部的悬停元素):

  • 听取mousemove事件。 目标是
    • event.target
    • document.elementFromPoint(event.clientX, event.clientY)

在不移动鼠标的情况下滚动时,这不起作用。 然后,鼠标在技术上不动; 因此,不会发生任何鼠标事件。

不幸的是,在收听scroll事件时,上述两种技术都不再适用。 event.target将是滚动(或document )的任何元素。 此外,鼠标光标位置未在event对象上公开。

正如在“确定鼠标指针位于Javascript顶部的哪个元素”的回答中所述 ,一种可能的解决方案是通过CSS :hover伪类查询悬停元素。

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

但是,这是不可用的,因为它非常低效且不准确。 scroll事件是快速触发事件之一,并且在执行任何稍微昂贵的任务时(例如查询DOM)需要减慢速度。

此外,滚动时悬停元素滞后 您可以在任何具有大量链接的网站上观察到这一点:将鼠标悬停在其中一个上并滚动到另一个链接而不移动鼠标。 它仅在几毫秒后更新。

有什么办法,这可以很好地实现吗? 基本上,我想要mouseenter的逆:我不想知道鼠标何时进入和元素,我想知道元素何时与鼠标相交(例如,当鼠标未被移动而是元素[即滚动时])。

解决此问题的一种方法是使用mousemove事件存储鼠标光标位置,并在scroll事件中使用document.elementFromPoint(x, y)来计算应该悬停的元素。

请记住,由于scroll事件以如此高的频率触发,这仍然是非常低效的。 应该去抖动事件处理程序以将函数的执行限制为每个延迟一次。 David Walsh在JavaScript Debounce Function中解释了如何做到这一点。

 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树中查找合适的元素。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM