如何用GSAP或原生JS实现网页平滑滚动?现有代码致动画异常
实现页面平滑滚动:原生JS修复与GSAP兼容方案
问题根源分析
你当前的原生JS平滑滚动代码,通过直接修改smooth-scroll-wrapper的transform属性模拟滚动,但这种方式会和GSAP动画产生冲突——GSAP也会操作元素的transform属性,两者的变换值会互相覆盖,最终导致页面动画混乱。此外,代码未处理窗口resize场景,会引发滚动区域高度异常。
方案1:修复后的原生JS实现(无GSAP依赖)
针对原代码的缺陷,调整如下:
const body = document.body; const scrollWrap = document.querySelector(".smooth-scroll-wrapper"); let height = scrollWrap.getBoundingClientRect().height - 1; const speed = 0.04; let offset = 0; let scrollRequestId; // 初始化/更新body高度,适配窗口变化 function updateBodyHeight() { height = scrollWrap.getBoundingClientRect().height - 1; body.style.height = `${Math.floor(height)}px`; } updateBodyHeight(); window.addEventListener("resize", updateBodyHeight); function smoothScroll() { offset += (window.pageYOffset - offset) * speed; scrollWrap.style.transform = `translateY(-${offset}px) translateZ(0)`; scrollRequestId = requestAnimationFrame(smoothScroll); } smoothScroll(); // 页面卸载时清理动画请求,避免内存泄漏 window.addEventListener("beforeunload", () => { cancelAnimationFrame(scrollRequestId); });
修复点说明:
- 用
querySelector替代getElementsByClassName,获取元素更简洁且返回静态节点 - 新增
updateBodyHeight函数处理窗口resize,保证滚动区域高度始终正确 - 新增动画请求清理逻辑,避免页面卸载后残留内存占用
方案2:GSAP实现平滑滚动(推荐,兼容其他GSAP动画)
既然你已经在使用GSAP,推荐用GSAP的ticker和gsap.set实现平滑滚动,能完美兼容其他GSAP动画,避免transform属性冲突:
const scrollWrap = document.querySelector(".smooth-scroll-wrapper"); let targetScroll = 0; let currentScroll = 0; const speed = 0.04; // 初始化/更新body高度 function updateBodyHeight() { const height = scrollWrap.getBoundingClientRect().height - 1; document.body.style.height = `${Math.floor(height)}px`; } updateBodyHeight(); window.addEventListener("resize", updateBodyHeight); // 监听原生滚动事件,记录目标滚动位置 window.addEventListener("scroll", () => { targetScroll = window.pageYOffset; }); // 用GSAP ticker替代requestAnimationFrame,同步GSAP动画时间轴 gsap.ticker.add(() => { currentScroll += (targetScroll - currentScroll) * speed; // 用gsap.set更新transform,GSAP会自动合并变换属性,避免覆盖其他动画 gsap.set(scrollWrap, { y: -currentScroll, z: 0 }); });
优势说明:
- GSAP的
ticker会自动对齐动画帧率,和其他GSAP动画(如位移、缩放)时间轴完全同步 gsap.set会智能合并transform属性,不会覆盖其他GSAP动画设置的变换值(比如x、scale),彻底解决动画混乱问题- 逻辑更简洁,无需手动管理
requestAnimationFrame的启停
额外提示
如果需要更高级的平滑滚动效果(如滚动吸附、视差联动),可以使用GSAP的ScrollSmoother插件(需GSAP商业授权),它专门为平滑滚动场景设计,提供开箱即用的高级功能。
内容的提问来源于stack exchange,提问作者NAYMUR
相关产品推荐
相关产品推荐

