动画
Vue 的 Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可轻松实现。
基础动画
你几乎所有的动画都将在一个<motion />
组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion-v"
<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: "0px" }' :animate='{ height: "auto" }' />
注意:如果还要将 display
动画到/出 "none"
,请将其替换为 visibility
"hidden"
,因为具有 display: none
的元素无法被测量。
Transforms (变换)
与 CSS 不同,Motion 可以独立地动画每个变换轴
Translate (位移):
x
、y
、z
Scale (缩放):
scale
、scaleX
、scaleY
Rotate (旋转):
rotate
、rotateX
、rotateY
、rotateZ
Skew (倾斜):
skew
、skewX
、skewY
Perspective (透视):
transformPerspective
motion
组件具有增强的 style
属性,允许你设置单独的变换
<motion.section :style="{ x: -20 }" />
独立地动画变换提供了极大的灵活性,尤其是在手势方面。
<motion.button :whileHover="{ scale: 1.1 }" whilePress="{ scale: 0.9 }" />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform
独特地提供了硬件加速。
<motion.li :initial='{ transform: "translateX(-100px)" }' :animate='{ transform: "translateX(0px)" }' :transition='{ type: "spring" }' />
SVG 注意: 对于 SVG 组件,x
和 y
属性 可以使用 attrX
和 attrY
设置。
Transform origin (变换原点)
transform-origin
具有三个快捷值,可以单独设置和动画
originX
originY
originZ
如果设置为数字,originX
和 Y
默认值为 0
和 1
之间的进度值。originZ
默认为像素。
<motion.div :style='{ originX: 0.5 }' />
CSS 变量
Vue 的 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 变量的值总是会触发重绘,因此使用 MotionValue
s来设置此类动画可能更高效。
CSS 变量作为动画目标
HTML motion
组件接受带有 CSS 变量的动画目标
<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />
SVG 线条绘制
可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLength
、pathSpacing
和 pathOffset
。
<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />
所有三个属性都设置为 0
和 1
之间的进度值,1
表示路径的总长度。
路径动画与 circle
、ellipse
、line
、path
、polygon
、polyline
和 rect
元素兼容。
过渡
默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。
例如,像 x
或 scale
这样的物理属性会使用弹簧物理效果进行动画,而像 opacity
或 color
这样的值会使用基于持续时间的缓动曲线进行动画。
但是,你可以通过在transition (过渡)
属性上的值.
<motion.div :animate="{ x: 100 }" :transition="{ ease: 'easeOut', duration: 2 }" />
来定义你自己的动画。
进入动画在当首次创建
属性来设置初始值),它将自动动画到 motion
组件时,如果 animate
中的值与最初渲染的值不同(你可以通过 CSS 或 initial
animate
中的值。
<motion.li :initial="{ opacity: 0, scale: 0 }" :animate="{ opacity: 1, scale: 1 }" />
你还可以通过设置 :initial="false"
完全禁用进入动画。这将使元素以 animate
中定义的值进行渲染。
<motion.div :initial="false" :animate="{ y: 100 }" />
退出动画
你还可以轻松地在元素退出 DOM 时为其添加动画效果。
在 Vue 中,当组件被移除时,通常会立即移除。Motion 提供了在AnimatePresence
组件上执行。AnimatePresence
<AnimatePresence> <motion.div v-if="isVisible" key="modal" :initial="{ opacity: 0 }" :animate="{ opacity: 1 }" :exit="{ opacity: 0 }" /> </AnimatePresence>
,它会在元素执行 exit
动画时将其保留在 DOM 中。
关键帧
<motion.div :animate="{ x: [0, 100, 0] }" />
animate
中的值可以设置为一系列关键帧。这将按顺序动画遍历每个值。
<motion.div :animate="{ x: [null, 100, 0] }" />
我们可以通过将一个值的当前状态设置为 null
来将其用作初始关键帧。
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。在默认情况下,每个关键帧在整个动画中自然分布。你可以通过在
times (时间)选项来覆盖此设置。transition
中设置
times
是一个介于 0
和 1
之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。
<motion.circle :cx="500" :animate="{ cx: [null, 100, 200], transition={{ duration: 3, times: [0, 0.2, 1] }} }" />
手势动画
Vue 的 Motion 库具有快捷属性,用于在手势开始/结束时动画到/从目标值。
<motion.button :initial="{ opacity: 0 }" :whileHover="{ backgroundColor: 'rgba(220, 220, 220, 1)' }" :whilePress="{ backgroundColor: 'rgba(255, 255, 255, 1)' }" :whileInView="{ opacity: 1 }" />
它支持 hover
、press
、drag
、focus
和 inView
。
Variants (变体)
将 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']"
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树结构的动画时变得非常强大。
变体将向下流经 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
属性传递
<motion.div v-for="(item,index) in items" :custom="index" :variants="variants" />
这样,可以为每个动画元素以不同的方式解析变体。
动画控制
声明式动画非常适合大多数 UI 交互。但有时我们需要手动控制动画播放。
可以使用 useAnimate
hook (钩子)来实现
动画任何 HTML/SVG 元素(不仅仅是
motion
组件)。复杂的动画序列。
使用
time
、speed
、play()
、pause()
和其他播放控件控制动画。
<script setup> const [scope, animate] = useAnimate() watch(scope, () => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }) </script> <template> <ul ref="scope"> <li /> <li /> <li /> </ul> </template>
动画内容
通过将一个MotionValue
作为 value 属性传递给 RowValue
组件,它将在 HTML 中渲染其最新值。
<script setup> import { useMotionValue, motion, animate, RowValue } from "motion-v" import { onMount, onUnmount } from "vue" const count = useMotionValue(0) let controls onMount(()=>{ controls = animate(count, 100, { duration: 5 }) }) onUnmount(()=>{ controls.stop() }) </script> <template> <motion.pre><RowValue :value="count"/></motion.pre> </template>
这比设置 Vue 状态更高效,因为 RowValue
组件将直接设置 innerHTML
。
Vue 的 Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可轻松实现。
基础动画
你几乎所有的动画都将在一个<motion />
组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion-v"
<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: "0px" }' :animate='{ height: "auto" }' />
注意:如果还要将 display
动画到/出 "none"
,请将其替换为 visibility
"hidden"
,因为具有 display: none
的元素无法被测量。
Transforms (变换)
与 CSS 不同,Motion 可以独立地动画每个变换轴
Translate (位移):
x
、y
、z
Scale (缩放):
scale
、scaleX
、scaleY
Rotate (旋转):
rotate
、rotateX
、rotateY
、rotateZ
Skew (倾斜):
skew
、skewX
、skewY
Perspective (透视):
transformPerspective
motion
组件具有增强的 style
属性,允许你设置单独的变换
<motion.section :style="{ x: -20 }" />
独立地动画变换提供了极大的灵活性,尤其是在手势方面。
<motion.button :whileHover="{ scale: 1.1 }" whilePress="{ scale: 0.9 }" />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform
独特地提供了硬件加速。
<motion.li :initial='{ transform: "translateX(-100px)" }' :animate='{ transform: "translateX(0px)" }' :transition='{ type: "spring" }' />
SVG 注意: 对于 SVG 组件,x
和 y
属性 可以使用 attrX
和 attrY
设置。
Transform origin (变换原点)
transform-origin
具有三个快捷值,可以单独设置和动画
originX
originY
originZ
如果设置为数字,originX
和 Y
默认值为 0
和 1
之间的进度值。originZ
默认为像素。
<motion.div :style='{ originX: 0.5 }' />
CSS 变量
Vue 的 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 变量的值总是会触发重绘,因此使用 MotionValue
s来设置此类动画可能更高效。
CSS 变量作为动画目标
HTML motion
组件接受带有 CSS 变量的动画目标
<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />
SVG 线条绘制
可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLength
、pathSpacing
和 pathOffset
。
<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />
所有三个属性都设置为 0
和 1
之间的进度值,1
表示路径的总长度。
路径动画与 circle
、ellipse
、line
、path
、polygon
、polyline
和 rect
元素兼容。
过渡
默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。
例如,像 x
或 scale
这样的物理属性会使用弹簧物理效果进行动画,而像 opacity
或 color
这样的值会使用基于持续时间的缓动曲线进行动画。
但是,你可以通过在transition (过渡)
属性上的值.
<motion.div :animate="{ x: 100 }" :transition="{ ease: 'easeOut', duration: 2 }" />
来定义你自己的动画。
进入动画在当首次创建
属性来设置初始值),它将自动动画到 motion
组件时,如果 animate
中的值与最初渲染的值不同(你可以通过 CSS 或 initial
animate
中的值。
<motion.li :initial="{ opacity: 0, scale: 0 }" :animate="{ opacity: 1, scale: 1 }" />
你还可以通过设置 :initial="false"
完全禁用进入动画。这将使元素以 animate
中定义的值进行渲染。
<motion.div :initial="false" :animate="{ y: 100 }" />
退出动画
你还可以轻松地在元素退出 DOM 时为其添加动画效果。
在 Vue 中,当组件被移除时,通常会立即移除。Motion 提供了在AnimatePresence
组件上执行。AnimatePresence
<AnimatePresence> <motion.div v-if="isVisible" key="modal" :initial="{ opacity: 0 }" :animate="{ opacity: 1 }" :exit="{ opacity: 0 }" /> </AnimatePresence>
,它会在元素执行 exit
动画时将其保留在 DOM 中。
关键帧
<motion.div :animate="{ x: [0, 100, 0] }" />
animate
中的值可以设置为一系列关键帧。这将按顺序动画遍历每个值。
<motion.div :animate="{ x: [null, 100, 0] }" />
我们可以通过将一个值的当前状态设置为 null
来将其用作初始关键帧。
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。在默认情况下,每个关键帧在整个动画中自然分布。你可以通过在
times (时间)选项来覆盖此设置。transition
中设置
times
是一个介于 0
和 1
之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。
<motion.circle :cx="500" :animate="{ cx: [null, 100, 200], transition={{ duration: 3, times: [0, 0.2, 1] }} }" />
手势动画
Vue 的 Motion 库具有快捷属性,用于在手势开始/结束时动画到/从目标值。
<motion.button :initial="{ opacity: 0 }" :whileHover="{ backgroundColor: 'rgba(220, 220, 220, 1)' }" :whilePress="{ backgroundColor: 'rgba(255, 255, 255, 1)' }" :whileInView="{ opacity: 1 }" />
它支持 hover
、press
、drag
、focus
和 inView
。
Variants (变体)
将 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']"
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树结构的动画时变得非常强大。
变体将向下流经 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
属性传递
<motion.div v-for="(item,index) in items" :custom="index" :variants="variants" />
这样,可以为每个动画元素以不同的方式解析变体。
动画控制
声明式动画非常适合大多数 UI 交互。但有时我们需要手动控制动画播放。
可以使用 useAnimate
hook (钩子)来实现
动画任何 HTML/SVG 元素(不仅仅是
motion
组件)。复杂的动画序列。
使用
time
、speed
、play()
、pause()
和其他播放控件控制动画。
<script setup> const [scope, animate] = useAnimate() watch(scope, () => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }) </script> <template> <ul ref="scope"> <li /> <li /> <li /> </ul> </template>
动画内容
通过将一个MotionValue
作为 value 属性传递给 RowValue
组件,它将在 HTML 中渲染其最新值。
<script setup> import { useMotionValue, motion, animate, RowValue } from "motion-v" import { onMount, onUnmount } from "vue" const count = useMotionValue(0) let controls onMount(()=>{ controls = animate(count, 100, { duration: 5 }) }) onUnmount(()=>{ controls.stop() }) </script> <template> <motion.pre><RowValue :value="count"/></motion.pre> </template>
这比设置 Vue 状态更高效,因为 RowValue
组件将直接设置 innerHTML
。
Vue 的 Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可轻松实现。
基础动画
你几乎所有的动画都将在一个<motion />
组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。
import { motion } from "motion-v"
<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: "0px" }' :animate='{ height: "auto" }' />
注意:如果还要将 display
动画到/出 "none"
,请将其替换为 visibility
"hidden"
,因为具有 display: none
的元素无法被测量。
Transforms (变换)
与 CSS 不同,Motion 可以独立地动画每个变换轴
Translate (位移):
x
、y
、z
Scale (缩放):
scale
、scaleX
、scaleY
Rotate (旋转):
rotate
、rotateX
、rotateY
、rotateZ
Skew (倾斜):
skew
、skewX
、skewY
Perspective (透视):
transformPerspective
motion
组件具有增强的 style
属性,允许你设置单独的变换
<motion.section :style="{ x: -20 }" />
独立地动画变换提供了极大的灵活性,尤其是在手势方面。
<motion.button :whileHover="{ scale: 1.1 }" whilePress="{ scale: 0.9 }" />
独立的变换性能出色,但 Motion 的混合引擎也通过直接设置 transform
独特地提供了硬件加速。
<motion.li :initial='{ transform: "translateX(-100px)" }' :animate='{ transform: "translateX(0px)" }' :transition='{ type: "spring" }' />
SVG 注意: 对于 SVG 组件,x
和 y
属性 可以使用 attrX
和 attrY
设置。
Transform origin (变换原点)
transform-origin
具有三个快捷值,可以单独设置和动画
originX
originY
originZ
如果设置为数字,originX
和 Y
默认值为 0
和 1
之间的进度值。originZ
默认为像素。
<motion.div :style='{ originX: 0.5 }' />
CSS 变量
Vue 的 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 变量的值总是会触发重绘,因此使用 MotionValue
s来设置此类动画可能更高效。
CSS 变量作为动画目标
HTML motion
组件接受带有 CSS 变量的动画目标
<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />
SVG 线条绘制
可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLength
、pathSpacing
和 pathOffset
。
<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />
所有三个属性都设置为 0
和 1
之间的进度值,1
表示路径的总长度。
路径动画与 circle
、ellipse
、line
、path
、polygon
、polyline
和 rect
元素兼容。
过渡
默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。
例如,像 x
或 scale
这样的物理属性会使用弹簧物理效果进行动画,而像 opacity
或 color
这样的值会使用基于持续时间的缓动曲线进行动画。
但是,你可以通过在transition (过渡)
属性上的值.
<motion.div :animate="{ x: 100 }" :transition="{ ease: 'easeOut', duration: 2 }" />
来定义你自己的动画。
进入动画在当首次创建
属性来设置初始值),它将自动动画到 motion
组件时,如果 animate
中的值与最初渲染的值不同(你可以通过 CSS 或 initial
animate
中的值。
<motion.li :initial="{ opacity: 0, scale: 0 }" :animate="{ opacity: 1, scale: 1 }" />
你还可以通过设置 :initial="false"
完全禁用进入动画。这将使元素以 animate
中定义的值进行渲染。
<motion.div :initial="false" :animate="{ y: 100 }" />
退出动画
你还可以轻松地在元素退出 DOM 时为其添加动画效果。
在 Vue 中,当组件被移除时,通常会立即移除。Motion 提供了在AnimatePresence
组件上执行。AnimatePresence
<AnimatePresence> <motion.div v-if="isVisible" key="modal" :initial="{ opacity: 0 }" :animate="{ opacity: 1 }" :exit="{ opacity: 0 }" /> </AnimatePresence>
,它会在元素执行 exit
动画时将其保留在 DOM 中。
关键帧
<motion.div :animate="{ x: [0, 100, 0] }" />
animate
中的值可以设置为一系列关键帧。这将按顺序动画遍历每个值。
<motion.div :animate="{ x: [null, 100, 0] }" />
我们可以通过将一个值的当前状态设置为 null
来将其用作初始关键帧。
这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。在默认情况下,每个关键帧在整个动画中自然分布。你可以通过在
times (时间)选项来覆盖此设置。transition
中设置
times
是一个介于 0
和 1
之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。
<motion.circle :cx="500" :animate="{ cx: [null, 100, 200], transition={{ duration: 3, times: [0, 0.2, 1] }} }" />
手势动画
Vue 的 Motion 库具有快捷属性,用于在手势开始/结束时动画到/从目标值。
<motion.button :initial="{ opacity: 0 }" :whileHover="{ backgroundColor: 'rgba(220, 220, 220, 1)' }" :whilePress="{ backgroundColor: 'rgba(255, 255, 255, 1)' }" :whileInView="{ opacity: 1 }" />
它支持 hover
、press
、drag
、focus
和 inView
。
Variants (变体)
将 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']"
传播
这对于重用和组合动画目标已经很有用。但它在编排整个树结构的动画时变得非常强大。
变体将向下流经 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
属性传递
<motion.div v-for="(item,index) in items" :custom="index" :variants="variants" />
这样,可以为每个动画元素以不同的方式解析变体。
动画控制
声明式动画非常适合大多数 UI 交互。但有时我们需要手动控制动画播放。
可以使用 useAnimate
hook (钩子)来实现
动画任何 HTML/SVG 元素(不仅仅是
motion
组件)。复杂的动画序列。
使用
time
、speed
、play()
、pause()
和其他播放控件控制动画。
<script setup> const [scope, animate] = useAnimate() watch(scope, () => { const controls = animate([ [scope.current, { x: "100%" }], ["li", { opacity: 1 }] ]) controls.speed = 0.8 return () => controls.stop() }) </script> <template> <ul ref="scope"> <li /> <li /> <li /> </ul> </template>
动画内容
通过将一个MotionValue
作为 value 属性传递给 RowValue
组件,它将在 HTML 中渲染其最新值。
<script setup> import { useMotionValue, motion, animate, RowValue } from "motion-v" import { onMount, onUnmount } from "vue" const count = useMotionValue(0) let controls onMount(()=>{ controls = animate(count, 100, { duration: 5 }) }) onUnmount(()=>{ controls.stop() }) </script> <template> <motion.pre><RowValue :value="count"/></motion.pre> </template>
这比设置 Vue 状态更高效,因为 RowValue
组件将直接设置 innerHTML
。