如何检测scrollTo滚动已完成并触发回调函数
检测滚动完成并触发回调的解决方案
当然有办法解决这个问题啦!你当前的代码里,直接在window.scrollTo之后调用callback()会立刻执行——因为当使用behavior: 'smooth'时,滚动是异步完成的,并不会阻塞后续代码执行。下面给你两种实用的方案:
方案一:使用scrollend事件(推荐,现代浏览器)
这是浏览器原生提供的滚动结束事件,专门用来监听滚动动作完成,代码简洁且可靠:
scrollToElementTop(element, offset, smooth, callback) { // 处理offset默认值,避免toFixed报错 offset = offset ? offset.toFixed() : 0; const positionTop = element.getBoundingClientRect().top + window.pageYOffset + offset; // 定义滚动结束后的处理函数 const handleScrollEnd = () => { callback(); // 执行完回调后移除监听,防止重复触发 window.removeEventListener('scrollend', handleScrollEnd); }; // 如果是平滑滚动,才添加监听 if (smooth) { window.addEventListener('scrollend', handleScrollEnd); } // 执行滚动 window.scrollTo({ top: positionTop, behavior: smooth ? 'smooth' : 'auto' }); // 非平滑滚动时,滚动会立刻完成,直接执行回调 if (!smooth) { callback(); } }
注意
scrollend事件支持Chrome 105+、Firefox 103+、Edge 105+等现代浏览器,如果你的项目需要兼容旧版浏览器,可以试试下面的方案。
方案二:定时检测滚动位置(兼容所有浏览器)
通过定时器定期检查当前滚动位置是否到达目标位置,以此判断滚动是否完成:
scrollToElementTop(element, offset, smooth, callback) { offset = offset ? offset.toFixed() : 0; const positionTop = element.getBoundingClientRect().top + window.pageYOffset + offset; // 取整避免浮点数精度问题 const targetPosition = Math.round(positionTop); // 执行滚动 window.scrollTo({ top: positionTop, behavior: smooth ? 'smooth' : 'auto' }); // 非平滑滚动直接执行回调 if (!smooth) { callback(); return; } // 定时检测滚动状态 const checkInterval = setInterval(() => { const currentPosition = Math.round(window.pageYOffset); // 允许±2的误差范围,避免滚动惯性导致的误判 if (Math.abs(currentPosition - targetPosition) <= 2) { clearInterval(checkInterval); callback(); } }, 50); // 每隔50ms检查一次,可根据需求调整 }
进阶优化
如果担心用户在自动滚动过程中手动干扰滚动,可以添加scroll事件监听,一旦检测到手动滚动就清除定时器/移除scrollend监听,避免错误触发回调。
内容的提问来源于stack exchange,提问作者Marek
相关产品推荐
相关产品推荐

