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

如何为Framer Motion动画添加条件控制,实现单卡片触发动画?

解决Framer Motion点击单张卡片仅触发该卡片动画的问题

我是React新手,制作了三张卡片并使用Framer Motion实现动画。我希望点击某一张卡片时仅该卡片触发动画,但目前点击任意卡片时三张卡片都会同时启动动画,请问如何为Framer Motion动画添加条件控制?

我的代码如下:

import "./styles.css";
import { useState,useEffect } from "react";
import { motion, useAnimationControls } from "framer-motion"


export default function App() {
  const [elements,setElements]=useState(['one','two','three'])
  const controls = useAnimationControls()


  return (
    <section className="App">
      {
        elements.map((Element,index)=>(
          <motion.div key={index}  animate={controls} onClick={()=>controls.start({ scale: 2 })}>{Element}</motion.div>
        ))
      }   
    </section>
  );
} 

核心问题原因

你当前的代码中所有卡片共用了同一个useAnimationControls控制器,所以点击任意卡片时,控制器会触发所有绑定它的motion组件执行动画。要实现单张卡片独立触发,需要让每个卡片拥有独立的动画控制逻辑。

方法一:用状态记录激活卡片索引(最简单方案)

通过useState记录当前被点击的卡片索引,每个卡片根据自身索引判断是否执行动画:

import "./styles.css";
import { useState } from "react";
import { motion } from "framer-motion"

export default function App() {
  const [elements, setElements] = useState(['one','two','three'])
  const [activeIndex, setActiveIndex] = useState(null)

  return (
    <section className="App">
      {
        elements.map((Element, index) => (
          <motion.div
            key={index}
            animate={activeIndex === index ? { scale: 2 } : { scale: 1 }}
            onClick={() => setActiveIndex(index)}
          >
            {Element}
          </motion.div>
        ))
      }   
    </section>
  );
} 

方法二:为每个卡片创建独立动画控制器(适合复杂动画)

如果需要更精细的动画控制(比如多阶段动画),可以给每个卡片单独生成控制器:

import "./styles.css";
import { useState, useMemo } from "react";
import { motion, useAnimationControls } from "framer-motion"

export default function App() {
  const [elements, setElements] = useState(['one','two','three'])
  // 为每个元素生成独立的动画控制器
  const controlsList = useMemo(() => 
    elements.map(() => useAnimationControls()), 
    [elements]
  )

  return (
    <section className="App">
      {
        elements.map((Element, index) => {
          const controls = controlsList[index]
          return (
            <motion.div
              key={index}
              animate={controls}
              onClick={() => controls.start({ scale: 2 })}
            >
              {Element}
            </motion.div>
          )
        })
      }   
    </section>
  );
} 

方法三:用Variants结合状态控制(适合复用动画配置)

如果需要复用多组动画状态,可以定义Variants来管理:

import "./styles.css";
import { useState } from "react";
import { motion } from "framer-motion"

// 定义动画状态集合
const cardVariants = {
  inactive: { scale: 1 },
  active: { scale: 2 }
}

export default function App() {
  const [elements, setElements] = useState(['one','two','three'])
  const [activeIndex, setActiveIndex] = useState(null)

  return (
    <section className="App">
      {
        elements.map((Element, index) => (
          <motion.div
            key={index}
            variants={cardVariants}
            initial="inactive"
            animate={activeIndex === index ? "active" : "inactive"}
            onClick={() => setActiveIndex(index)}
          >
            {Element}
          </motion.div>
        ))
      }   
    </section>
  );
} 

内容的提问来源于stack exchange,提问作者ABIDI MarWen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:40:33