AI 摘要
生成中...
Variants 属性在 Framer Motion 中是一种定义可重用动画状态的方式。它们允许您创建复杂的、协调的动画,而无需在每个组件上单独定义动画属性。
基本概念
Variants 是一个对象,其中包含了命名的动画状态。每个状态可以定义元素的样式和动画属性。
基本用法
- 定义 Variants
const variants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}- 使用 Variants
<motion.div variants={variants} initial="hidden" animate="visible" />高级特性
- 动态 Variants
Variants 可以是函数,接收自定义参数:
const variants = {
hidden: { opacity: 0, y: 20 },
visible: (custom) => ({
opacity: 1,
y: 0,
transition: { delay: custom * 0.2 }
})
}
<motion.div
variants={variants}
custom={index} // 传递索引作为自定义参数
initial="hidden"
animate="visible"
/>- Variant 传播
父元素的 variant 会自动传播到子元素:
const list = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { when: 'beforeChildren', staggerChildren: 0.3, }, }, } const item = { hidden: { y: 20, opacity: 0 }, visible: { y: 0, opacity: 1 }, } function List() { return ( <motion.ul variants={list} initial="hidden" animate="visible"> {items.map((item) => ( <motion.li key={item} variants={item} /> ))} </motion.ul> ) }
- 循环动画
使用 repeat 和 repeatType 创建循环动画:
const variants = {
animate: {
scale: [1, 1.2, 1],
transition: {
duration: 2,
repeat: Infinity,
repeatType: 'reverse',
},
},
}- 条件 Variants
基于条件选择不同的 variant:
function Box({ isOn }) {
const variants = {
on: { backgroundColor: '#f00' },
off: { backgroundColor: '#ccc' },
}
return <motion.div variants={variants} animate={isOn ? 'on' : 'off'} />
}- 组合 Variants
可以组合多个 variants 来创建复杂的动画序列:
const button = {
tap: { scale: 0.9 },
hover: { scale: 1.1 },
initial: { scale: 1 }
}
<motion.button
variants={button}
initial="initial"
whileHover="hover"
whileTap="tap"
>
Click me
</motion.button>实际应用示例
让我们看一个更复杂的例子,展示如何使用 variants 创建一个动画列表:
import { motion } from 'motion/react' const container = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.1, }, }, } const item = { hidden: { opacity: 0, y: 50 }, show: { opacity: 1, y: 0, transition: { type: 'spring', stiffness: 300, damping: 24, }, }, } function AnimatedList({ items }) { return ( <motion.ul variants={container} initial="hidden" animate="show"> {items.map((text, index) => ( <motion.li key={index} variants={item}> {text} </motion.li> ))} </motion.ul> ) }
在这个例子中,我们定义了两个 variants:一个用于容器(container),一个用于每个列表项(item)。容器 variant 使用 staggerChildren 来创建一个错开的动画效果,而每个项目则有自己的弹簧动画。
这种方法的优势在于:
- 动画逻辑与组件逻辑分离
- 可以轻松地在不同组件间重用动画
- 通过父子关系自动协调复杂的动画序列
通过掌握 variants,您可以创建出复杂、协调且可重用的动画,大大提高动画开发的效率和灵活性。