如何在div滚动时或滚动结束后立即用原生JS检测鼠标位置
问题原因
scroll事件属于页面视图变动类事件,本身不携带鼠标坐标属性,所以直接从scroll事件对象中读取clientY/clientX必然返回undefined,只有鼠标交互类事件(如mousemove、mousedown等)的事件对象才会携带坐标属性。
优化实现方案
按照你只需要滚动触发时、滚动结束时获取鼠标坐标的需求,我们可以采用「滚动期间临时监听mousemove,滚动结束后立即移除监听」的逻辑,避免全局持续监听mousemove造成的性能浪费,原生实现代码如下:
完整实现代码
HTML
<div id="container"> <div id="content"></div> </div> <div id="clientY_display">Scroll to see event.clientY position.. </div>
CSS
#container { height: 50px; } #content { height: 1000px; background-color: rgba(120,120,120,1); } #clientY_display { position: fixed; }
JS
const clientYDisplay = document.getElementById("clientY_display"); // 存储最新鼠标坐标 let mousePos = { x: 0, y: 0 }; // 防抖计时器 let scrollTimer = null; // 标记是否已经绑定了mousemove监听,避免重复绑定 let isListeningMouse = false; // 鼠标移动监听函数 const handleMouseMove = e => { mousePos.x = e.clientX; mousePos.y = e.clientY; // 滚动过程中可以实时更新坐标,如果不需要可以删掉下一行,只在滚动结束更新 clientYDisplay.textContent = `滚动中坐标:clientY = ${mousePos.y}, clientX = ${mousePos.x}`; }; // 滚动监听函数 const handleScroll = () => { // 滚动触发时如果还没绑定鼠标监听就绑定 if (!isListeningMouse) { document.addEventListener('mousemove', handleMouseMove); isListeningMouse = true; } // 防抖判断滚动结束:150ms内没有新的滚动事件就判定为滚动结束 clearTimeout(scrollTimer); scrollTimer = setTimeout(() => { // 滚动结束后移除鼠标监听,避免不必要的性能消耗 document.removeEventListener('mousemove', handleMouseMove); isListeningMouse = false; // 输出滚动结束时的最终坐标 clientYDisplay.textContent = `滚动结束坐标:clientY = ${mousePos.y}, clientX = ${mousePos.x}`; }, 150); }; document.addEventListener('scroll', handleScroll);
方案说明
- 只有滚动触发后的150ms内会临时监听mousemove事件,页面无滚动时不会执行任何多余的监听逻辑,性能开销极低
- 可以自行调整防抖的150ms参数,数值越大滚动结束判定越宽松,越小越敏感
- 如果不需要滚动过程中实时更新坐标,只需要滚动结束后的结果,删掉
handleMouseMove里的实时更新行即可
内容的提问来源于stack exchange,提问作者Normajean
相关产品推荐
相关产品推荐

