如何在Framer Motion中实现单个组件动画序列的无限循环
如何在Framer Motion中实现单个组件动画序列的无限循环
嘿,我明白你现在的需求啦——你已经写好了一段连贯的动画序列,但希望它能一直循环播放,对吧?其实实现起来很简单,咱们可以利用递归调用的方式,让动画序列在完成后自动重启。
你现在的runAnimation函数只会在组件挂载时执行一次,执行完整个序列就结束了。要让它无限循环,只需要在所有动画步骤完成后,再次调用runAnimation本身就行。
修改后的代码示例
const [scope, animate] = useAnimate(); const runAnimation = async () => { await animate(scope.current, { x: 300 }, { duration: 2 }); await animate(scope.current, { scaleX: -1 }, { duration: 0.2 }); await animate(scope.current, { x: -200 }, { duration: 2 }); await animate(scope.current, { scaleX: 1 }, { duration: 0.2 }); // 动画序列完成后递归调用自身,触发下一轮循环 runAnimation(); }; useEffect(() => { runAnimation(); }, []);
这样一来,每当四个动画步骤全部执行完毕,函数就会立刻重新启动整个序列,形成无限循环的效果。
进阶:可控的循环(可选)
如果之后你需要手动控制循环的启停,可以添加一个状态变量来管理:
import { useState } from 'react'; import { useAnimate } from 'framer-motion'; // ... const [scope, animate] = useAnimate(); const [isLooping, setIsLooping] = useState(true); const runAnimation = async () => { // 如果已经停止循环,直接退出 if (!isLooping) return; await animate(scope.current, { x: 300 }, { duration: 2 }); await animate(scope.current, { scaleX: -1 }, { duration: 0.2 }); await animate(scope.current, { x: -200 }, { duration: 2 }); await animate(scope.current, { scaleX: 1 }, { duration: 0.2 }); // 再次检查循环状态,确保只有在开启状态下才继续 if (isLooping) { runAnimation(); } }; useEffect(() => { runAnimation(); // 组件卸载时停止循环,避免内存泄漏 return () => setIsLooping(false); }, []); // 之后可以通过按钮等触发setIsLooping(true/false)来控制循环
这种递归的方式非常适合你这种多步骤的序列动画,能完美保持动画的顺序和连贯性,而且几乎不需要改动原有代码逻辑。
备注:内容来源于stack exchange,提问作者abhi jain
相关产品推荐
相关产品推荐

