触摸板滚动JS问题:如何抑制惯性滚动或限制滚动事件触发次数?
解决触摸板惯性滚动导致wheel事件频繁触发的问题
在网站上使用双指触摸板滚动时,会触发1-1.5秒的惯性滚动,执行
console.log('scroll')会输出68次,导致程序在操作后仍多次延迟触发滚动事件。尝试过防抖、解绑再绑定事件均无效,现有wheel事件处理代码如下:
document.addEventListener("wheel", this.wheelFilter, {passive: false}); wheelFilter = e => { this.updateWheelPrevTime(); this.preventParentScroll(); if ( this._wheelTimeDiff > this._REAL_SCROLL_TIME ) { this.onMouseWheel(e); } else { this.updateWheelFireTime(); } }
请教如何消除触摸板滚动的惯性,或限制滚动事件的触发次数?
方案一:识别触摸板惯性滚动并过滤
触摸板惯性滚动的事件有明显特征:e.deltaMode为像素模式(值为0),且单次滚动的deltaX/deltaY数值极小,连续触发间隔极短。可以基于这个特征直接过滤惯性阶段的事件:
// 新增变量标记是否处于惯性滚动阶段 let isInertialScroll = false; // 阈值:单次滚动的delta绝对值小于此值则判定为惯性滚动 const INERTIAL_THRESHOLD = 3; wheelFilter = e => { this.updateWheelPrevTime(); this.preventParentScroll(); // 判断是否为惯性滚动事件 const isSmallDelta = Math.abs(e.deltaY) < INERTIAL_THRESHOLD && Math.abs(e.deltaX) < INERTIAL_THRESHOLD; if (isSmallDelta) { isInertialScroll = true; // 跳过惯性阶段的事件触发 return; } else { isInertialScroll = false; } if (this._wheelTimeDiff > this._REAL_SCROLL_TIME) { this.onMouseWheel(e); } else { this.updateWheelFireTime(); } }
方案二:改用scroll事件结合节流逻辑
防抖是等待事件停止后触发,不适合滚动场景;节流是固定间隔触发,能有效限制事件触发次数。如果业务逻辑允许,可替换原wheel事件为scroll事件加节流:
// 基础节流函数 function throttle(func, delay) { let lastTriggerTime = 0; return function(...args) { const now = Date.now(); if (now - lastTriggerTime >= delay) { func.apply(this, args); lastTriggerTime = now; } } } // 替换原wheel事件绑定 document.addEventListener("scroll", throttle(this.handleScroll, 100), {passive: true}); // 滚动处理逻辑 handleScroll = () => { // 执行原onMouseWheel对应的业务代码 }
方案三:直接禁用原生惯性滚动(谨慎使用)
通过CSS属性禁用浏览器原生惯性滚动,但会影响滚动体验,仅适合对滚动精度要求极高的场景:
/* 给目标滚动容器添加以下样式 */ .target-scroll-container { overscroll-behavior: contain; scroll-behavior: auto; /* 针对iOS设备禁用惯性滚动 */ -webkit-overflow-scrolling: auto; }
注意:-webkit-overflow-scrolling: auto会让iOS设备上的滚动变得生硬,需要在功能需求和用户体验间权衡。
内容的提问来源于stack exchange,提问作者Turan
相关产品推荐
相关产品推荐

