Firefox中释放滚动时scroll-snap的scrollend事件触发两次的问题
解决Firefox中scroll-snap场景下scrollend事件触发两次的问题
在使用scroll-snap实现滚动对齐的容器中,Firefox会触发两次scrollend事件:第一次在用户停止交互(松开滚轮/手指)时触发,第二次在滚动对齐动画完成时触发。两次事件间隔极短且事件对象无差异,以下是两种可行的区分方法,仅处理动画完成的第二次事件。
原问题代码复现
.viewport { width:100px; height:100px; white-space:nowrap; overflow:auto; display:inline-block; scroll-snap-type: x mandatory; } .viewport > div { width:100px; height:100px; display:inline-block; scroll-snap-align: center; } .red{background:red;} .green{background:green;} .blue{background:blue;}
<div class="viewport"> <div class="red">»</div> <div class="green">»</div> <div class="blue">»</div> </div>
方法一:防抖函数过滤重复事件
利用两次事件间隔极短的特性,通过防抖函数只保留最后一次事件的回调执行,精准捕获动画完成的触发时机。
const viewport = document.querySelector('.viewport'); // 防抖函数,延迟50ms执行回调,可根据实际测试调整时长 const debounce = (func, delay = 50) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; }; // 业务逻辑处理函数 const handleFinalScrollEnd = (event) => { console.log('滚动对齐完成:', event); // 此处编写你的业务代码 }; viewport.addEventListener('scrollend', debounce(handleFinalScrollEnd));
原理说明
第一次scrollend触发后,防抖函数会启动定时器,但很快第二次事件会触发并清除之前的定时器,只有当延迟时间内无新事件触发时,才会执行最终的回调逻辑,确保只处理动画完成的那次事件。
方法二:检查滚动位置稳定性
通过requestAnimationFrame循环检测滚动位置是否稳定,判断动画是否完成,无需依赖固定延迟时间,适配性更强。
const viewport = document.querySelector('.viewport'); let lastScrollLeft = 0; let isCheckingStability = false; const handleScrollEnd = (event) => { if (isCheckingStability) return; isCheckingStability = true; const checkScrollStable = () => { const currentScrollLeft = viewport.scrollLeft; if (currentScrollLeft === lastScrollLeft) { // 滚动位置连续两帧不变,说明动画完成 console.log('滚动对齐完成:', event); isCheckingStability = false; } else { lastScrollLeft = currentScrollLeft; requestAnimationFrame(checkScrollStable); } }; lastScrollLeft = viewport.scrollLeft; requestAnimationFrame(checkScrollStable); }; viewport.addEventListener('scrollend', handleScrollEnd);
原理说明
每次scrollend触发时,启动循环检测滚动位置:如果连续两帧的滚动位置完全一致,说明滚动对齐动画已经结束,此时执行业务逻辑;否则继续检测,直到位置稳定。
内容的提问来源于stack exchange,提问作者Grim
相关产品推荐
相关产品推荐

