如何使用Framer Motion实现一个动画结束后再启动另一个动画?
如何用Framer Motion实现动画顺序执行
要实现一个动画结束后再启动另一个,有两种实用方案,直接看代码和说明:
方案1:用useAnimationControls实现自动序列动画
适合组件挂载后自动按顺序执行动画的场景,核心是通过控制方法的序列调用实现顺序触发。
首先定义动画变体(示例):
const variants1 = { hidden: { opacity: 0, y: -20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5 } } }; const variants2 = { hidden: { opacity: 0, scale: 0.8 }, visible: { opacity: 1, scale: 1, transition: { duration: 0.5 } } };
然后编写组件逻辑:
import { motion, useAnimationControls } from "framer-motion"; import { useEffect, useRef } from "react"; export default function SequentialAnimations() { const controls = useAnimationControls(); // 注意:每个元素的ref必须单独定义,不能共用 const element1Ref = useRef(null); const element2Ref = useRef(null); useEffect(() => { // 按顺序执行:先触发第一个元素的动画,完成后再触发第二个 controls.start([ () => element1Ref.current?.animate("visible"), () => element2Ref.current?.animate("visible") ]); }, [controls]); return ( <> <motion.div variants={variants1} initial="hidden" ref={element1Ref} > Start animation one </motion.div> <motion.div variants={variants2} initial="hidden" ref={element2Ref} > Start animation Two </motion.div> </> ); }
方案2:利用onComplete或await手动触发序列
适合需要通过用户操作(比如点击按钮)启动动画的场景,灵活控制触发时机。
import { motion, useAnimation } from "framer-motion"; export default function SequentialAnimations() { const variants1 = { hidden: { opacity: 0, y: -20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5 } } }; const variants2 = { hidden: { opacity: 0, scale: 0.8 }, visible: { opacity: 1, scale: 1, transition: { duration: 0.5 } } }; const controls1 = useAnimation(); const controls2 = useAnimation(); const triggerAnimations = async () => { // 启动第一个动画,等待它执行完成 await controls1.start("visible"); // 第一个动画结束后,启动第二个 controls2.start("visible"); }; return ( <> <button onClick={triggerAnimations}>启动序列动画</button> <motion.div variants={variants1} initial="hidden" animate={controls1} > Start animation one </motion.div> <motion.div variants={variants2} initial="hidden" animate={controls2} > Start animation Two </motion.div> </> ); }
关键注意点
- 多个动画元素不能共用同一个ref,需单独定义或使用独立的控制实例
- 序列执行的核心是等待前一个动画完成,不管用
controls.start的数组序列还是await语法,本质都是这个逻辑 - 如果需要更复杂的序列控制,还可以在
transition里配置delay,但这种方式不如上述方法灵活可控
内容的提问来源于stack exchange,提问作者Wael Manai
相关产品推荐
相关产品推荐

