React中使用Framer Motion实现列表平滑无缝循环动画咨询
问题根因
当前代码出现跳变卡顿、滚动空白的核心原因有3个:
- 仅配置了transition属性,没有给motion组件绑定正确的x轴动画起止值,动画逻辑不完整
- 仅渲染了单组合作伙伴列表,列表滚动到左边界后没有后续内容补位,重置位置时必然出现断层
- 容器错误使用
overflow-x-scroll,且没有做首尾位置对齐,循环重启时视觉跳变明显
无缝跑马灯实现方案
核心实现逻辑:将原列表复制1份拼接在尾部,配合精确的半程位移动画,当第一组列表完全移出左侧可视区时,第二组列表刚好占据第一组的初始位置,此时将x轴位移重置为0,视觉上完全无跳变,实现无限匀速滚动。
完整实现代码
// 修正列表数据结构,保证每个项有唯一alt和资源地址 const partners = [ { alt: "partner1", src: "/partner1.png" }, { alt: "partner2", src: "/partner2.png" }, { alt: "partner3", src: "/partner3.png" }, // 其他列表项... ] // 外层固定可视区域容器 <div className="h-36 bg-transparent w-3/4 overflow-hidden"> <motion.div className="h-full flex flex-row flex-nowrap items-center" animate={{ x: ["0%", "-50%"] }} transition={{ duration: 8, // 滚动速度可自行调整,数值越大速度越慢 ease: "linear", // 必须设置线性缓动,保证匀速运动 repeat: Infinity, }} > {/* 渲染第一组原列表 */} {partners.map((partner) => ( <div key={partner.alt} className="h-24 w-24 lg:h-32 lg:w-32 z-10 relative flex-shrink-0 mx-8" > <Image layout="fill" className="h-full w-full object-cover grayscale" alt={partner.alt} src={partner.src} /> </div> ))} {/* 拼接第二组相同列表,实现无缝补位 */} {partners.map((partner) => ( <div key={`copy-${partner.alt}`} className="h-24 w-24 lg:h-32 lg:w-32 z-10 relative flex-shrink-0 mx-8" > <Image layout="fill" className="h-full w-full object-cover grayscale" alt={partner.alt} src={partner.src} /> </div> ))} </motion.div> </div>
关键注意点
- 不要给做动画的内层motion容器设置
justify-center,否则初始列表居中会导致右侧出现空白 - 列表项的间距统一用
mx-*控制,不要混用容器padding和space-x,避免宽度计算偏差导致的微小跳变 - 如果需要反向滚动(从左向右),只需要把动画x值改成
["-50%", "0%"]即可 - 动画时长根据列表总长度调整,保证滚动速度符合视觉预期即可
- 外层容器必须设置
overflow: hidden,替换原来的overflow-x-scroll,裁剪溢出内容同时隐藏滚动条 - 原代码中无效类名
lg:32已修正为lg:h-32,避免样式失效
内容的提问来源于stack exchange,提问作者Taio
相关产品推荐
相关产品推荐

