如何在Framer Motion中修改无限动画时长且不重置动画进度
解决方案
方案1:调整动画播放速率(最优解,无动画断层)
核心逻辑是不要每次修改时长就销毁重建动画,直接通过Framer Motion动画控制器提供的setRate方法调整播放速度,等效实现修改duration的效果,全程不会打断动画,循环范围也能保持1~2不变:
const [count, setCount] = useState(1); const scale = useMotionValue(1); // 存储动画控制器,避免重复创建动画 const controlsRef = React.useRef(null); // 仅初始化时创建一次动画 React.useEffect(() => { controlsRef.current = animate(scale, [1, 2], { repeat: Infinity, ease: "linear", duration: 1 // 固定基础时长,用速率控制实际时长 }); return () => controlsRef.current.stop(); }, [scale]); // 时长参数变化时仅调整播放速率 React.useEffect(() => { if (controlsRef.current) { // 播放速率与目标时长成反比:目标时长越长,播放速度越慢 controlsRef.current.setRate(1 / count); } }, [count]);
方案2:重建动画时手动补偿进度
如果必须每次修改时长都重建动画,可以在重建前计算当前动画的完成进度,通过负延迟让新动画直接跳到对应进度开始播放,避免重置或循环范围偏移:
const [count, setCount] = useState(1); const scale = useMotionValue(1); React.useEffect(() => { // 计算当前动画进度 const currentScale = scale.get(); const progress = (currentScale - 1) / (2 - 1); const controls = animate(scale, [1, 2], { repeat: Infinity, ease: "linear", duration: count, // 负延迟会直接跳过对应时长的动画,从进度匹配的位置开始播放 delay: -progress * count }); return controls.stop; }, [scale, count]);
内容的提问来源于stack exchange,提问作者Bastien Robert
相关产品推荐
相关产品推荐

