如何在页面滚动时为图片/容器添加类视差动画效果?
滚动扩宽+类视差效果实现方案
你之前用JS搭配CSS动画达不到效果,核心问题是把滚动驱动的交互动画做成了时间驱动的CSS关键帧动画,属性变化和实际滚动位置不绑定,且宽度、位移两个属性用了完全一致的变化速率,自然出不了错位的视差感。
原生无插件实现(性能最优,适合定制化需求)
核心实现逻辑:
- 预留足够的滚动容器高度,让目标图片用sticky定位固定在视口内,留出动画触发的滚动区间
- 用
requestAnimationFrame做滚动事件节流,避免频繁触发重绘导致掉帧 - 计算0-1区间的滚动进度值,给宽度、横向位移两个属性设置不同的进度映射系数,制造速率差:比如宽度随滚动进度1:1变化,横向位移只跟随进度走80%左右的对应距离,自然形成类视差的错位感
- 直接通过内联样式修改元素属性,不要额外加CSS transition,避免动画和滚动位置脱节产生延迟感
可直接复用的代码示例:
<style> .scroll-trigger-section { position: relative; /* 高度设为180vh,留出足够滚动空间触发完整动画 */ height: 180vh; } .effect-target-img { position: sticky; top: 0; /* 初始状态:右对齐,占视口一半宽度 */ width: 50vw; margin-left: auto; height: 100vh; object-fit: cover; will-change: width, transform; } </style> <section class="scroll-trigger-section"> <img class="effect-target-img" src="你的图片资源路径" alt="展示素材"> </section> <script> const targetImg = document.querySelector('.effect-target-img'); const triggerSection = document.querySelector('.scroll-trigger-section'); // 动画参数配置,可根据需求调整 const ANIMATION_SCROLL_DISTANCE = 620; // 滚动620px完成全宽过渡 const OFFSET_RATE = 0.83; // 横向位移的速率系数,小于1时位移比宽度变化慢,形成视差错位 function syncEffectWithScroll() { const sectionRect = triggerSection.getBoundingClientRect(); // 计算当前滚动进度,强制限制在0-1区间避免越界 let scrollProgress = Math.abs(sectionRect.top) / ANIMATION_SCROLL_DISTANCE; scrollProgress = Math.max(0, Math.min(1, scrollProgress)); // 宽度映射:从50vw逐步过渡到100vw const currentWidth = 50 + 50 * scrollProgress; targetImg.style.width = `${currentWidth}vw`; // 横向位移映射:速率比宽度慢,制造错位感 const currentOffset = (window.innerWidth * 0.5 * scrollProgress) * OFFSET_RATE; targetImg.style.transform = `translateX(-${currentOffset}px)`; requestAnimationFrame(syncEffectWithScroll); } // 初始化启动效果 requestAnimationFrame(syncEffectWithScroll); </script>
参数调整提示:
- 调大
ANIMATION_SCROLL_DISTANCE数值会拉长动画触发的滚动距离,动画过渡会更平缓 OFFSET_RATE建议设置在0.7-0.9区间,数值越小视差错位感越强,0.83是最接近你参考案例的效果- 如果需要给图片本身加内层视差,只需要额外加个scale属性的映射,比如初始scale为1.08,滚动完成时scale为1,同样跟随进度变化即可
插件方案(适合快速开发,减少调试成本)
- 如果项目有较多复杂滚动交互,直接用GSAP搭配ScrollTrigger能力即可,内置了滚动进度计算、边界判断、平滑滚动适配的能力,不需要自己手写进度计算逻辑,只需要给宽度、位移属性配置不同的变化速率就能实现效果,移动端兼容性也更稳定,不会出现滚动抖动问题
- 轻量场景如果只需要解决原生滚动的跳变问题,可以引入lenis做平滑滚动基础,搭配上面的原生逻辑使用,能大幅提升动画跟手度
注意:不建议用纯CSS的滚动驱动动画实现该效果,目前Safari全版本对该特性支持度极差,面向客户的商用项目上线后会出现大面积兼容问题。
内容的提问来源于stack exchange,提问作者Tom Durkin
相关产品推荐
相关产品推荐

