React 动画
React Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可实现。
基本动画
你几乎所有的动画都将在一个<motion />组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion/react"
<motion.div animate={{ opacity: 1 }} />
。当其 animate 属性中的任何值发生更改时,组件将自动动画到新目标。
可动画化的值
Motion 可以动画化任何 CSS 值,甚至包括浏览器无法动画化的值,例如 mask-image。它支持
数字:
0、100等。包含数字的字符串:
"0vh"、"10px"等。颜色:Hex、RGBA、HSLA。
包含多个数字和/或颜色的复杂字符串(如
box-shadow)。display: "none"/"block"和visibility: "hidden"/"visible"。
值类型转换
通常,值只能在两种相同类型之间进行动画处理(即 "0px" 到 "100px")。
颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。
此外,x、y、width、height、top、left、right 和 bottom 可以在不同的值类型之间进行动画处理。
<motion.div initial={{ x: "100%" }} animate={{ x: "calc(100vw - 50%)" }} />
也可以将 width 和 height 动画到/出 "auto"。
<motion.div initial={{ height: 0 }} animate={{ height: "auto" }} />
注意:如果还要将 display 动画到/出 "none",请用 visibility "hidden" 替换它,因为具有 display: none 的元素无法被测量。
变换
与 CSS 不同,Motion 可以独立地动画化每个变换轴
平移:
x、y、z缩放:
scale、scaleX、scaleY旋转:
rotate、rotateX、rotateY、rotateZ倾斜:
skew、skewX、skewY透视:
transformPerspective
motion 组件具有增强的 style 属性,允许你设置单独的变换
<motion.section style={{ x: -20 }} />
独立地动画化变换提供了极大的灵活性,尤其是在手势方面。
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform 独特地提供了硬件加速。
<motion.li initial={{ transform: "translateX(-100px)" }} animate={{ transform: "translateX(0px)" }} transition={{ type: "spring" }} />
SVG 注意:对于 SVG 组件,可以使用 attrX 和 attrY 设置 x 和 y 属性。
变换原点
transform-origin 具有三个可以单独设置和动画化的快捷值
originXoriginYoriginZ
如果设置为数字,originX 和 Y 默认为 0 和 1 之间的进度值。originZ 默认为像素。
<motion.div style={{ originX: 0.5 }} />
CSS 变量
React Motion 库可以动画化 CSS 变量的值,也可以使用 CSS 变量作为动画目标。
动画化 CSS 变量
有时,为了动画化多个子元素,能够动画化 CSS 变量会很方便
<motion.ul initial={{ '--rotate': '0deg' }} animate={{ '--rotate': '360deg' }} transition={{ duration: 2, repeat: Infinity }} > <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> </motion.ul>
注意:动画化 CSS 变量的值始终会触发重绘,因此使用 MotionValues来设置这种动画可能更高效。
CSS 变量作为动画目标
HTML motion 组件接受带有 CSS 变量的动画目标
<motion.li animate={{ backgroundColor: "var(--action-bg)" }} />
SVG 线条绘制
可以使用三个特殊的属性创建线条绘制动画:pathLength、pathSpacing 和 pathOffset,它们可以用于许多不同的 SVG 元素。
<motion.path initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} />
这三个属性都设置为 0 和 1 之间的进度值,1 代表路径的总长度。
路径动画与 circle、ellipse、line、path、polygon、polyline 和 rect 元素兼容。
过渡
默认情况下,Motion 将基于正在动画化的值的类型创建适当的过渡,以实现快速动画。
例如,像 x 或 scale 这样的物理属性使用弹簧物理动画,而像 opacity 或 color 这样的值则使用基于持续时间的缓动曲线进行动画处理。
但是,你可以通过animatetransitionprop.
<motion.div animate={{ x: 100 }} transition={{ ease: "easeOut", duration: 2 }} />
定义自己的动画
进入动画animate当首次创建 initial motion 组件时,如果 animate 中的值与最初渲染的值不同(你可以通过 CSS 或通过
<motion.li initial={{ opacity: 0, scale: 0 }} animate={{ opacity: 1, scale: 1 }} />
属性执行初始渲染),它将自动动画到 animate 中的值。你也可以通过设置 initial={false} 完全禁用进入动画。这将使元素以 animate 中定义的值进行渲染。
<motion.div initial={false} animate={{ y: 100 }} />
退出动画
你也可以轻松地在元素退出 DOM 时为其添加动画。
在 React 中,当组件被移除时,通常会立即移除。Motion 提供了animateAnimatePresence组件上执行,它可以在元素执行 exit 动画时将其保留在 DOM 中。
<AnimatePresence> {isVisible && ( <motion.div key="modal" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} /> )} </AnimatePresence>
关键帧
animate 中的值可以设置为一系列关键帧。这将按顺序动画化每个值。
<motion.div animate={{ x: [0, 100, 0] }} />
我们可以通过将值的当前状态设置为 null 来将其用作初始关键帧。
<motion.div animate={{ x: [null, 100, 0] }} />
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。
默认情况下,每个关键帧在整个动画中自然间隔。你可以通过 transition 设置animatetimes选项来覆盖此默认行为。
times 是一个介于 0 和 1 之间的进度值数组,用于定义每个关键帧在动画中的位置。
<motion.circle cx={500} animate={{ cx: [null, 100, 200], transition: { duration: 3, times: [0, 0.2, 1] } }} />
手势动画
React Motion 库具有快捷属性,用于在手势开始/结束时动画化到/从目标。
<motion.button initial={{ opacity: 0 }} whileHover={{ backgroundColor: "rgba(220, 220, 220, 1)" }} whileTap={{ backgroundColor: "rgba(255, 255, 255, 1)" }} whileInView={{ opacity: 1 }} />
它支持 hover、tap、drag、focus 和 inView。
变体
将 animate 设置为目标对于简单的单元素动画很有用。但有时我们希望编排在整个 DOM 中传播的动画。我们可以使用变体来实现。
变体是一组命名的目标。
const variants = { visible: { opacity: 1 }, hidden: { opacity: 0 }, }
它们通过 variants 属性传递给 motion 组件
<motion.div variants={variants} />
现在可以在任何可以定义动画目标的地方通过标签引用这些变体
<motion.div variants={variants} initial="hidden" whileInView="visible" />
你也可以通过数组定义多个变体
animate={["visible", "danger"]}
我喜欢将变体与 React 状态一起使用 – 只需将你的状态传递给
animate,现在你就有了一个整洁的地方来定义所有动画目标!const [status, setStatus] = useState<"inactive" | "active" | "complete">( "inactive" ); <motion.div animate={status} // pass in our React state! variants={{ inactive: { scale: 0.9 color: "var(--gray-500)" }, active: { scale: 1 color: "var(--blue-500)" }, complete: { scale: 1 color: "var(--blue-500)" } }} > <motion.svg path={checkmarkPath} variants={{ inactive: { pathLength: 0 }, active: { pathLength: 0 }, complete: { pathLength: 1} }} /> </motion.div>~ Sam Selikoff,React Motion 库食谱
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树的动画时变得更加强大。
变体将向下流动通过 motion 组件。因此,在此示例中,当 ul 进入视口时,其所有具有“visible”变体的子元素也将动画进入
const list = { visible: { opacity: 1 }, hidden: { opacity: 0 }, } const item = { visible: { opacity: 1, x: 0 }, hidden: { opacity: 0, x: -100 }, } return ( <motion.ul initial="hidden" whileInView="visible" variants={list} > <motion.li variants={item} /> <motion.li variants={item} /> <motion.li variants={item} /> </motion.ul> )
编排
默认情况下,此子动画将与父动画同时开始。但是通过变体,我们可以访问新的 transition 属性,例如 when, delayChildren, staggerChildren和staggerDirection.
const list = { visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.3, // Stagger children by .3 seconds }, }, hidden: { opacity: 0, transition: { when: "afterChildren", }, }, }
动态变体
每个变体都可以定义为一个函数,该函数在变体变为活动状态时解析。
const variants = { hidden: { opacity: 0 }, visible: (index) => ({ opacity: 1, transition: { delay: index * 0.3 } }) }
这些函数被提供了一个参数,该参数通过 custom 属性传递
items.map((item, index) => <motion.div custom={index} variants={variants} />)
这样,每个动画元素的变体都可以以不同的方式解析。
动画控制
声明式动画是大多数 UI 交互的理想选择。但有时我们需要手动控制动画播放。
useAnimatehook可以用于
动画化任何 HTML/SVG 元素(不仅仅是
motion组件)。复杂的动画序列。
使用
time、speed、play()、pause()和其他播放控件控制动画。
function MyComponent() { const [scope, animate] = useAnimate() useEffect(() => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }, []) return ( <ul ref={scope}> <li /> <li /> <li /> </ul> ) }
动画内容
通过传递一个MotionValue 作为 motion 组件的子元素,它将在 HTML 中渲染其最新值。
import { useMotionValue, motion, animate } from "motion/react" function Counter() { const count = useMotionValue(0) useEffect(() => { const controls = animate(count, 100, { duration: 5 }) return () => controls.stop() }, []) return <motion.pre>{count}</motion.pre> }
这比设置 React 状态更高效,因为 motion 组件将直接设置 innerHTML。
React Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可实现。
基本动画
你几乎所有的动画都将在一个<motion />组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion/react"
<motion.div animate={{ opacity: 1 }} />
。当其 animate 属性中的任何值发生更改时,组件将自动动画到新目标。
可动画化的值
Motion 可以动画化任何 CSS 值,甚至包括浏览器无法动画化的值,例如 mask-image。它支持
数字:
0、100等。包含数字的字符串:
"0vh"、"10px"等。颜色:Hex、RGBA、HSLA。
包含多个数字和/或颜色的复杂字符串(如
box-shadow)。display: "none"/"block"和visibility: "hidden"/"visible"。
值类型转换
通常,值只能在两种相同类型之间进行动画处理(即 "0px" 到 "100px")。
颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。
此外,x、y、width、height、top、left、right 和 bottom 可以在不同的值类型之间进行动画处理。
<motion.div initial={{ x: "100%" }} animate={{ x: "calc(100vw - 50%)" }} />
也可以将 width 和 height 动画到/出 "auto"。
<motion.div initial={{ height: 0 }} animate={{ height: "auto" }} />
注意:如果还要将 display 动画到/出 "none",请用 visibility "hidden" 替换它,因为具有 display: none 的元素无法被测量。
变换
与 CSS 不同,Motion 可以独立地动画化每个变换轴
平移:
x、y、z缩放:
scale、scaleX、scaleY旋转:
rotate、rotateX、rotateY、rotateZ倾斜:
skew、skewX、skewY透视:
transformPerspective
motion 组件具有增强的 style 属性,允许你设置单独的变换
<motion.section style={{ x: -20 }} />
独立地动画化变换提供了极大的灵活性,尤其是在手势方面。
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform 独特地提供了硬件加速。
<motion.li initial={{ transform: "translateX(-100px)" }} animate={{ transform: "translateX(0px)" }} transition={{ type: "spring" }} />
SVG 注意:对于 SVG 组件,可以使用 attrX 和 attrY 设置 x 和 y 属性。
变换原点
transform-origin 具有三个可以单独设置和动画化的快捷值
originXoriginYoriginZ
如果设置为数字,originX 和 Y 默认为 0 和 1 之间的进度值。originZ 默认为像素。
<motion.div style={{ originX: 0.5 }} />
CSS 变量
React Motion 库可以动画化 CSS 变量的值,也可以使用 CSS 变量作为动画目标。
动画化 CSS 变量
有时,为了动画化多个子元素,能够动画化 CSS 变量会很方便
<motion.ul initial={{ '--rotate': '0deg' }} animate={{ '--rotate': '360deg' }} transition={{ duration: 2, repeat: Infinity }} > <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> </motion.ul>
注意:动画化 CSS 变量的值始终会触发重绘,因此使用 MotionValues来设置这种动画可能更高效。
CSS 变量作为动画目标
HTML motion 组件接受带有 CSS 变量的动画目标
<motion.li animate={{ backgroundColor: "var(--action-bg)" }} />
SVG 线条绘制
可以使用三个特殊的属性创建线条绘制动画:pathLength、pathSpacing 和 pathOffset,它们可以用于许多不同的 SVG 元素。
<motion.path initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} />
这三个属性都设置为 0 和 1 之间的进度值,1 代表路径的总长度。
路径动画与 circle、ellipse、line、path、polygon、polyline 和 rect 元素兼容。
过渡
默认情况下,Motion 将基于正在动画化的值的类型创建适当的过渡,以实现快速动画。
例如,像 x 或 scale 这样的物理属性使用弹簧物理动画,而像 opacity 或 color 这样的值则使用基于持续时间的缓动曲线进行动画处理。
但是,你可以通过animatetransitionprop.
<motion.div animate={{ x: 100 }} transition={{ ease: "easeOut", duration: 2 }} />
定义自己的动画
进入动画animate当首次创建 initial motion 组件时,如果 animate 中的值与最初渲染的值不同(你可以通过 CSS 或通过
<motion.li initial={{ opacity: 0, scale: 0 }} animate={{ opacity: 1, scale: 1 }} />
属性执行初始渲染),它将自动动画到 animate 中的值。你也可以通过设置 initial={false} 完全禁用进入动画。这将使元素以 animate 中定义的值进行渲染。
<motion.div initial={false} animate={{ y: 100 }} />
退出动画
你也可以轻松地在元素退出 DOM 时为其添加动画。
在 React 中,当组件被移除时,通常会立即移除。Motion 提供了animateAnimatePresence组件上执行,它可以在元素执行 exit 动画时将其保留在 DOM 中。
<AnimatePresence> {isVisible && ( <motion.div key="modal" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} /> )} </AnimatePresence>
关键帧
animate 中的值可以设置为一系列关键帧。这将按顺序动画化每个值。
<motion.div animate={{ x: [0, 100, 0] }} />
我们可以通过将值的当前状态设置为 null 来将其用作初始关键帧。
<motion.div animate={{ x: [null, 100, 0] }} />
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。
默认情况下,每个关键帧在整个动画中自然间隔。你可以通过 transition 设置animatetimes选项来覆盖此默认行为。
times 是一个介于 0 和 1 之间的进度值数组,用于定义每个关键帧在动画中的位置。
<motion.circle cx={500} animate={{ cx: [null, 100, 200], transition: { duration: 3, times: [0, 0.2, 1] } }} />
手势动画
React Motion 库具有快捷属性,用于在手势开始/结束时动画化到/从目标。
<motion.button initial={{ opacity: 0 }} whileHover={{ backgroundColor: "rgba(220, 220, 220, 1)" }} whileTap={{ backgroundColor: "rgba(255, 255, 255, 1)" }} whileInView={{ opacity: 1 }} />
它支持 hover、tap、drag、focus 和 inView。
变体
将 animate 设置为目标对于简单的单元素动画很有用。但有时我们希望编排在整个 DOM 中传播的动画。我们可以使用变体来实现。
变体是一组命名的目标。
const variants = { visible: { opacity: 1 }, hidden: { opacity: 0 }, }
它们通过 variants 属性传递给 motion 组件
<motion.div variants={variants} />
现在可以在任何可以定义动画目标的地方通过标签引用这些变体
<motion.div variants={variants} initial="hidden" whileInView="visible" />
你也可以通过数组定义多个变体
animate={["visible", "danger"]}
我喜欢将变体与 React 状态一起使用 – 只需将你的状态传递给
animate,现在你就有了一个整洁的地方来定义所有动画目标!const [status, setStatus] = useState<"inactive" | "active" | "complete">( "inactive" ); <motion.div animate={status} // pass in our React state! variants={{ inactive: { scale: 0.9 color: "var(--gray-500)" }, active: { scale: 1 color: "var(--blue-500)" }, complete: { scale: 1 color: "var(--blue-500)" } }} > <motion.svg path={checkmarkPath} variants={{ inactive: { pathLength: 0 }, active: { pathLength: 0 }, complete: { pathLength: 1} }} /> </motion.div>~ Sam Selikoff,React Motion 库食谱
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树的动画时变得更加强大。
变体将向下流动通过 motion 组件。因此,在此示例中,当 ul 进入视口时,其所有具有“visible”变体的子元素也将动画进入
const list = { visible: { opacity: 1 }, hidden: { opacity: 0 }, } const item = { visible: { opacity: 1, x: 0 }, hidden: { opacity: 0, x: -100 }, } return ( <motion.ul initial="hidden" whileInView="visible" variants={list} > <motion.li variants={item} /> <motion.li variants={item} /> <motion.li variants={item} /> </motion.ul> )
编排
默认情况下,此子动画将与父动画同时开始。但是通过变体,我们可以访问新的 transition 属性,例如 when, delayChildren, staggerChildren和staggerDirection.
const list = { visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.3, // Stagger children by .3 seconds }, }, hidden: { opacity: 0, transition: { when: "afterChildren", }, }, }
动态变体
每个变体都可以定义为一个函数,该函数在变体变为活动状态时解析。
const variants = { hidden: { opacity: 0 }, visible: (index) => ({ opacity: 1, transition: { delay: index * 0.3 } }) }
这些函数被提供了一个参数,该参数通过 custom 属性传递
items.map((item, index) => <motion.div custom={index} variants={variants} />)
这样,每个动画元素的变体都可以以不同的方式解析。
动画控制
声明式动画是大多数 UI 交互的理想选择。但有时我们需要手动控制动画播放。
useAnimatehook可以用于
动画化任何 HTML/SVG 元素(不仅仅是
motion组件)。复杂的动画序列。
使用
time、speed、play()、pause()和其他播放控件控制动画。
function MyComponent() { const [scope, animate] = useAnimate() useEffect(() => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }, []) return ( <ul ref={scope}> <li /> <li /> <li /> </ul> ) }
动画内容
通过传递一个MotionValue 作为 motion 组件的子元素,它将在 HTML 中渲染其最新值。
import { useMotionValue, motion, animate } from "motion/react" function Counter() { const count = useMotionValue(0) useEffect(() => { const controls = animate(count, 100, { duration: 5 }) return () => controls.stop() }, []) return <motion.pre>{count}</motion.pre> }
这比设置 React 状态更高效,因为 motion 组件将直接设置 innerHTML。
React Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可实现。
基本动画
你几乎所有的动画都将在一个<motion />组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion/react"
<motion.div animate={{ opacity: 1 }} />
。当其 animate 属性中的任何值发生更改时,组件将自动动画到新目标。
可动画化的值
Motion 可以动画化任何 CSS 值,甚至包括浏览器无法动画化的值,例如 mask-image。它支持
数字:
0、100等。包含数字的字符串:
"0vh"、"10px"等。颜色:Hex、RGBA、HSLA。
包含多个数字和/或颜色的复杂字符串(如
box-shadow)。display: "none"/"block"和visibility: "hidden"/"visible"。
值类型转换
通常,值只能在两种相同类型之间进行动画处理(即 "0px" 到 "100px")。
颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。
此外,x、y、width、height、top、left、right 和 bottom 可以在不同的值类型之间进行动画处理。
<motion.div initial={{ x: "100%" }} animate={{ x: "calc(100vw - 50%)" }} />
也可以将 width 和 height 动画到/出 "auto"。
<motion.div initial={{ height: 0 }} animate={{ height: "auto" }} />
注意:如果还要将 display 动画到/出 "none",请用 visibility "hidden" 替换它,因为具有 display: none 的元素无法被测量。
变换
与 CSS 不同,Motion 可以独立地动画化每个变换轴
平移:
x、y、z缩放:
scale、scaleX、scaleY旋转:
rotate、rotateX、rotateY、rotateZ倾斜:
skew、skewX、skewY透视:
transformPerspective
motion 组件具有增强的 style 属性,允许你设置单独的变换
<motion.section style={{ x: -20 }} />
独立地动画化变换提供了极大的灵活性,尤其是在手势方面。
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform 独特地提供了硬件加速。
<motion.li initial={{ transform: "translateX(-100px)" }} animate={{ transform: "translateX(0px)" }} transition={{ type: "spring" }} />
SVG 注意:对于 SVG 组件,可以使用 attrX 和 attrY 设置 x 和 y 属性。
变换原点
transform-origin 具有三个可以单独设置和动画化的快捷值
originXoriginYoriginZ
如果设置为数字,originX 和 Y 默认为 0 和 1 之间的进度值。originZ 默认为像素。
<motion.div style={{ originX: 0.5 }} />
CSS 变量
React Motion 库可以动画化 CSS 变量的值,也可以使用 CSS 变量作为动画目标。
动画化 CSS 变量
有时,为了动画化多个子元素,能够动画化 CSS 变量会很方便
<motion.ul initial={{ '--rotate': '0deg' }} animate={{ '--rotate': '360deg' }} transition={{ duration: 2, repeat: Infinity }} > <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> <li style={{ transform: 'rotate(var(--rotate))' }} /> </motion.ul>
注意:动画化 CSS 变量的值始终会触发重绘,因此使用 MotionValues来设置这种动画可能更高效。
CSS 变量作为动画目标
HTML motion 组件接受带有 CSS 变量的动画目标
<motion.li animate={{ backgroundColor: "var(--action-bg)" }} />
SVG 线条绘制
可以使用三个特殊的属性创建线条绘制动画:pathLength、pathSpacing 和 pathOffset,它们可以用于许多不同的 SVG 元素。
<motion.path initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} />
这三个属性都设置为 0 和 1 之间的进度值,1 代表路径的总长度。
路径动画与 circle、ellipse、line、path、polygon、polyline 和 rect 元素兼容。
过渡
默认情况下,Motion 将基于正在动画化的值的类型创建适当的过渡,以实现快速动画。
例如,像 x 或 scale 这样的物理属性使用弹簧物理动画,而像 opacity 或 color 这样的值则使用基于持续时间的缓动曲线进行动画处理。
但是,你可以通过animatetransitionprop.
<motion.div animate={{ x: 100 }} transition={{ ease: "easeOut", duration: 2 }} />
定义自己的动画
进入动画animate当首次创建 initial motion 组件时,如果 animate 中的值与最初渲染的值不同(你可以通过 CSS 或通过
<motion.li initial={{ opacity: 0, scale: 0 }} animate={{ opacity: 1, scale: 1 }} />
属性执行初始渲染),它将自动动画到 animate 中的值。你也可以通过设置 initial={false} 完全禁用进入动画。这将使元素以 animate 中定义的值进行渲染。
<motion.div initial={false} animate={{ y: 100 }} />
退出动画
你也可以轻松地在元素退出 DOM 时为其添加动画。
在 React 中,当组件被移除时,通常会立即移除。Motion 提供了animateAnimatePresence组件上执行,它可以在元素执行 exit 动画时将其保留在 DOM 中。
<AnimatePresence> {isVisible && ( <motion.div key="modal" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} /> )} </AnimatePresence>
关键帧
animate 中的值可以设置为一系列关键帧。这将按顺序动画化每个值。
<motion.div animate={{ x: [0, 100, 0] }} />
我们可以通过将值的当前状态设置为 null 来将其用作初始关键帧。
<motion.div animate={{ x: [null, 100, 0] }} />
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。
默认情况下,每个关键帧在整个动画中自然间隔。你可以通过 transition 设置animatetimes选项来覆盖此默认行为。
times 是一个介于 0 和 1 之间的进度值数组,用于定义每个关键帧在动画中的位置。
<motion.circle cx={500} animate={{ cx: [null, 100, 200], transition: { duration: 3, times: [0, 0.2, 1] } }} />
手势动画
React Motion 库具有快捷属性,用于在手势开始/结束时动画化到/从目标。
<motion.button initial={{ opacity: 0 }} whileHover={{ backgroundColor: "rgba(220, 220, 220, 1)" }} whileTap={{ backgroundColor: "rgba(255, 255, 255, 1)" }} whileInView={{ opacity: 1 }} />
它支持 hover、tap、drag、focus 和 inView。
变体
将 animate 设置为目标对于简单的单元素动画很有用。但有时我们希望编排在整个 DOM 中传播的动画。我们可以使用变体来实现。
变体是一组命名的目标。
const variants = { visible: { opacity: 1 }, hidden: { opacity: 0 }, }
它们通过 variants 属性传递给 motion 组件
<motion.div variants={variants} />
现在可以在任何可以定义动画目标的地方通过标签引用这些变体
<motion.div variants={variants} initial="hidden" whileInView="visible" />
你也可以通过数组定义多个变体
animate={["visible", "danger"]}
我喜欢将变体与 React 状态一起使用 – 只需将你的状态传递给
animate,现在你就有了一个整洁的地方来定义所有动画目标!const [status, setStatus] = useState<"inactive" | "active" | "complete">( "inactive" ); <motion.div animate={status} // pass in our React state! variants={{ inactive: { scale: 0.9 color: "var(--gray-500)" }, active: { scale: 1 color: "var(--blue-500)" }, complete: { scale: 1 color: "var(--blue-500)" } }} > <motion.svg path={checkmarkPath} variants={{ inactive: { pathLength: 0 }, active: { pathLength: 0 }, complete: { pathLength: 1} }} /> </motion.div>~ Sam Selikoff,React Motion 库食谱
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树的动画时变得更加强大。
变体将向下流动通过 motion 组件。因此,在此示例中,当 ul 进入视口时,其所有具有“visible”变体的子元素也将动画进入
const list = { visible: { opacity: 1 }, hidden: { opacity: 0 }, } const item = { visible: { opacity: 1, x: 0 }, hidden: { opacity: 0, x: -100 }, } return ( <motion.ul initial="hidden" whileInView="visible" variants={list} > <motion.li variants={item} /> <motion.li variants={item} /> <motion.li variants={item} /> </motion.ul> )
编排
默认情况下,此子动画将与父动画同时开始。但是通过变体,我们可以访问新的 transition 属性,例如 when, delayChildren, staggerChildren和staggerDirection.
const list = { visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.3, // Stagger children by .3 seconds }, }, hidden: { opacity: 0, transition: { when: "afterChildren", }, }, }
动态变体
每个变体都可以定义为一个函数,该函数在变体变为活动状态时解析。
const variants = { hidden: { opacity: 0 }, visible: (index) => ({ opacity: 1, transition: { delay: index * 0.3 } }) }
这些函数被提供了一个参数,该参数通过 custom 属性传递
items.map((item, index) => <motion.div custom={index} variants={variants} />)
这样,每个动画元素的变体都可以以不同的方式解析。
动画控制
声明式动画是大多数 UI 交互的理想选择。但有时我们需要手动控制动画播放。
useAnimatehook可以用于
动画化任何 HTML/SVG 元素(不仅仅是
motion组件)。复杂的动画序列。
使用
time、speed、play()、pause()和其他播放控件控制动画。
function MyComponent() { const [scope, animate] = useAnimate() useEffect(() => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }, []) return ( <ul ref={scope}> <li /> <li /> <li /> </ul> ) }
动画内容
通过传递一个MotionValue 作为 motion 组件的子元素,它将在 HTML 中渲染其最新值。
import { useMotionValue, motion, animate } from "motion/react" function Counter() { const count = useMotionValue(0) useEffect(() => { const controls = animate(count, 100, { duration: 5 }) return () => controls.stop() }, []) return <motion.pre>{count}</motion.pre> }
这比设置 React 状态更高效,因为 motion 组件将直接设置 innerHTML。
