React+Framer Motion动画执行延迟时间不一致问题求助
解决Framer Motion动画时序不稳定及端点回调问题
核心问题分析
你当前的实现依赖onAnimationComplete手动触发下一段动画,时序偏差的主要原因:
setState是异步操作,await setGoingRight(!goingRight)无法等待状态更新完成,导致后续controls.start调用时机不准- 手动启动动画过程中,React状态更新、函数执行带来的额外耗时,累加后造成不稳定的延迟
而无限重复动画的问题在于onAnimationComplete仅在整个循环结束时触发,无法捕获单次端点到达事件。
解决方案:用内置循环动画+重复回调
直接利用Framer Motion的内置循环动画能力,让框架自身调度动画时序,同时通过onRepeat和onAnimationComplete捕获每次端点到达事件:
import React, { useState, useRef } from "react"; import './Line.css'; import { motion } from 'framer-motion'; export const Line = ({ speed }) => { const [delay, setDelay] = useState(1000); const lastTriggerTime = useRef(Date.now()); // 到达端点时执行的逻辑 const handleEndReached = () => { const currentTime = Date.now(); setDelay(currentTime - lastTriggerTime.current); lastTriggerTime.current = currentTime; // 在这里添加你需要在端点执行的代码 console.log("圆形到达端点"); }; return ( <> {delay} <div className='outer'> <motion.div className='ball' initial={{ x: 0 }} animate={{ x: [0, 280, 0], // 定义动画路径:左→右→左 }} transition={{ duration: speed, // 单程动画时长 ease: "linear", repeat: Infinity, // 无限重复 repeatType: "reverse", // 反向重复,形成往复运动 // 每次重复触发(对应到达端点后准备反向时) onRepeat: handleEndReached }} // 处理第一次到达右侧端点的情况(此时还未进入重复循环) onAnimationComplete={handleEndReached} /> <div className='line' /> </div> </> ); };
方案优势
- 时序精准:动画由Framer Motion内部的动画引擎调度,基于RequestAnimationFrame实现精确的时间控制,完全避免手动启动动画带来的额外耗时,
delay会稳定在speed * 1000毫秒左右 - 端点回调可靠:
onAnimationComplete处理第一次从左到右的端点到达事件onRepeat在每次动画反向时触发,对应每次到达端点的时机
- 代码更简洁:去掉了复杂的状态管理和手动动画控制逻辑,减少出错概率
额外优化建议
- 如果不需要实时显示
delay,可以去掉delay状态和相关代码,避免不必要的重渲染 - 若需要更精细的端点判断,可以结合
onUpdate监听x属性的变化,配合useRef做防抖处理,避免重复触发回调
内容的提问来源于stack exchange,提问作者lsreale
相关产品推荐
相关产品推荐

