如何使用JS实现与页面滚动同步的持续水平动画
与页面滚动同步的水平动画实现方案
核心思路是放弃阈值触发类切换的两状态动画逻辑,实时计算当前滚动位置在动画区间内的进度占比,直接给目标元素设置对应位移值,实现滚动距离和动画进度1:1完全同步。
原有代码缺陷
现有逻辑仅判断滚动值是否超过50px阈值,超过就直接触发CSS预设的完整过渡,只有初始、结束两个固定状态,无法跟随滚动操作实时变化。
完整实现代码
样式部分
移除原有类切换和过渡逻辑,改用性能更优的transform实现位移,去掉会导致操作延迟的transition属性:
section { height: 600px; border-bottom: solid 1px #000; overflow: hidden; } h1 { display: block; font-size: 10rem; color: #999; white-space: nowrap; will-change: transform; }
脚本部分
加入requestAnimationFrame做性能优化,避免滚动事件高频触发导致掉帧,实时计算进度更新位移:
const targetTx = document.querySelector('h1'); // 动画配置项,可根据实际需求调整 const animateConfig = { startScrollY: 0, // 动画启动对应的页面滚动距离(单位:px) endScrollY: 600, // 动画结束对应的页面滚动距离(单位:px,当前值等于第一个section高度,滚完该区域动画刚好走完) maxOffsetX: -50 // 动画终点的水平位移距离(单位:%,和原示例的margin-left: -50%效果一致) } let ticking = false; function syncAnimate() { const currentScroll = window.scrollY; // 计算当前滚动进度,将值限制在0-1区间,避免超出动画范围 let progress = (currentScroll - animateConfig.startScrollY) / (animateConfig.endScrollY - animateConfig.startScrollY); progress = Math.max(0, Math.min(1, progress)); // 按进度计算当前位移值,实时更新样式 const offsetX = progress * animateConfig.maxOffsetX; targetTx.style.transform = `translateX(${offsetX}%)`; ticking = false; } window.addEventListener('scroll', () => { if (!ticking) { window.requestAnimationFrame(syncAnimate); ticking = true; } });
页面结构
沿用原有结构无需修改:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <section> <h1>TEST TEXT</h1> </section> <section></section> </body> </html>
自定义调整说明
- 调整动画触发区间:修改
animateConfig中的startScrollY和endScrollY值即可,例如需要从滚动200px开始启动动画,到滚动1000px时动画结束,直接替换对应数值 - 调整位移幅度:修改
maxOffsetX值即可,需要文字完全移出左侧可视区设为-100,需要向右移动则传入正值 - 扩展其他同步动画:如果需要同步实现透明度、缩放、旋转等效果,只需要把计算得到的
progress值映射到对应CSS属性的取值区间即可,逻辑通用。
内容的提问来源于stack exchange,提问作者Stan Law
相关产品推荐
相关产品推荐

