You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:15:43