求React实现类似Framer官网的无限图片流动动画(CSS/JS)方案
实现类似Framer官网的无限图片流动动画(React + CSS + JS方案)
核心实现思路
Framer官网的主视觉无限图片流核心是横向无缝循环滚动+分层视觉效果,关键逻辑:
- 采用「双容器复用」技巧:创建两个完全相同的图片列表容器,当第一个容器完全滚出视口时,将其重置到第二个容器的末尾,实现无感知的无限循环
- 通过CSS的
transform(位移、缩放)和opacity属性,给不同图片设置差异化的大小、透明度,模拟空间深度感 - 用JS驱动滚动动画,通过
requestAnimationFrame保证动画流畅度,避免CSS动画在复杂场景下的卡顿
代码实现示例
React组件结构
import { useRef, useEffect, useState } from 'react'; const InfiniteImageFlow = () => { const containerRef = useRef(null); const [images, setImages] = useState([ // 替换成你的图片地址,建议使用不同比例的图片增强层次感 '/img1.jpg', '/img2.jpg', '/img3.jpg', '/img4.jpg', '/img5.jpg' ]); const scrollPosition = useRef(0); const animationRef = useRef(null); // 生成重复的图片列表(双容器复用) const doubledImages = [...images, ...images]; useEffect(() => { const animate = () => { if (!containerRef.current) return; // 控制滚动速度,数值越小越慢 scrollPosition.current -= 0.5; // 当滚动距离达到单个容器宽度时重置,实现循环 const singleContainerWidth = containerRef.current.offsetWidth / 2; if (Math.abs(scrollPosition.current) >= singleContainerWidth) { scrollPosition.current = 0; } containerRef.current.style.transform = `translateX(${scrollPosition.current}px)`; animationRef.current = requestAnimationFrame(animate); }; animationRef.current = requestAnimationFrame(animate); return () => { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } }; }, []); return ( <div className="image-flow-wrapper"> <div ref={containerRef} className="image-flow-container"> {doubledImages.map((img, idx) => ( <div key={idx} className="image-item"> <img src={img} alt={`flow-img-${idx}`} /> </div> ))} </div> </div> ); }; export default InfiniteImageFlow;
CSS样式
.image-flow-wrapper { position: relative; width: 100%; height: 600px; /* 对应主视觉区域高度 */ overflow: hidden; background: #000; } .image-flow-container { position: absolute; top: 50%; left: 0; display: flex; gap: 2rem; transform: translateY(-50%); will-change: transform; /* 告诉浏览器提前优化动画 */ } .image-item { flex-shrink: 0; /* 自适应大小,兼顾不同屏幕 */ width: clamp(200px, 30vw, 400px); opacity: 0.6; } .image-item img { width: 100%; height: auto; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); } /* 给不同位置的图片设置差异化样式,增强层次感 */ .image-item:nth-child(2n) { transform: translateY(-10%) scale(0.9); opacity: 0.8; } .image-item:nth-child(3n) { transform: translateY(10%) scale(1.1); opacity: 0.7; }
关键技术优化建议
- 性能优化:
- 给动画容器添加
will-change: transform,触发GPU加速,减少页面重绘 - 图片优先使用WebP格式压缩体积,避免大资源拖慢动画
- 始终用
requestAnimationFrame替代setInterval,保证动画与浏览器刷新同步
- 给动画容器添加
- 视觉增强:
- 通过JS动态给每个图片生成随机的
translateY、scale、opacity值,比CSS伪类控制更自然 - 可添加鼠标交互:监听鼠标移动位置,让图片滚动速度随鼠标偏移实时变化
- 通过JS动态给每个图片生成随机的
- 响应式适配:
- 使用
clamp()、vw单位设置图片大小,自动适配不同屏幕宽度 - 在小屏设备上降低滚动速度,避免视觉杂乱
- 使用
- 图片加载:
- 实现图片懒加载,避免初始加载过多资源
- 给图片添加占位骨架,提升用户等待体验
内容的提问来源于stack exchange,提问作者JJang
相关产品推荐
相关产品推荐

