文档

文档

Vue

概述

动画

Vue 的 Motion 库提供了多种方式来为你的 UI 添加动画效果。从极其简单的基于属性的动画,到更复杂的编排,均可轻松实现。

基础动画

你几乎所有的动画都将在一个<motion />组件上执行。这基本上是一个具有 motion 超能力的 DOM 元素。

import { motion } from "motion-v"

对于基础动画,你可以更新animate属性上的值:

<motion.div :animate="{ opacity: 1 }" />

当 animate 属性中的任何值发生更改时,组件将自动动画到新的目标值。

可动画的值

Motion 可以动画任何 CSS 值,甚至包括浏览器无法动画的值,例如 mask-image。它支持

  • 数字:0100 等。

  • 包含数字的字符串:"0vh""10px" 等。

  • 颜色:Hex、RGBA、HSLA。

  • 包含多个数字和/或颜色的复杂字符串(例如 box-shadow)。

  • display: "none"/"block"visibility: "hidden"/"visible"

值类型转换

通常,值只能在两种相同类型之间进行动画(例如,"0px""100px")。

颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。

此外,xywidthheighttopleftrightbottom 可以在不同的值类型之间动画。

<motion.div
  :initial='{ x: "100%" }'
  :animate='{ x: "calc(100vw - 50%)" }'
/>

也可以将 widthheight 动画到/出 "auto"

<motion.div
  :initial='{ height: "0px" }'
  :animate='{ height: "auto" }'
/>

注意:如果还要将 display 动画到/出 "none",请将其替换为 visibility "hidden",因为具有 display: none 的元素无法被测量。

Transforms (变换)

与 CSS 不同,Motion 可以独立地动画每个变换轴

  • Translate (位移):xyz

  • Scale (缩放):scalescaleXscaleY

  • Rotate (旋转):rotaterotateXrotateYrotateZ

  • Skew (倾斜):skewskewXskewY

  • 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 组件,xy 属性 可以使用 attrXattrY 设置。

Transform origin (变换原点)

transform-origin 具有三个快捷值,可以单独设置和动画

  • originX

  • originY

  • originZ

如果设置为数字,originXY 默认值为 01 之间的进度值。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 变量的值总是会触发重绘,因此使用 MotionValues来设置此类动画可能更高效。

CSS 变量作为动画目标

HTML motion 组件接受带有 CSS 变量的动画目标

<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />

SVG 线条绘制

可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLengthpathSpacingpathOffset

<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />

所有三个属性都设置为 01 之间的进度值,1 表示路径的总长度。

路径动画与 circleellipselinepathpolygonpolylinerect 元素兼容。

过渡

默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。

例如,像 xscale 这样的物理属性会使用弹簧物理效果进行动画,而像 opacitycolor 这样的值会使用基于持续时间的缓动曲线进行动画。

但是,你可以通过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 来将其用作初始关键帧。

这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。默认情况下,每个关键帧在整个动画中自然分布。你可以通过在 transition 中设置times (时间)选项来覆盖此设置。

times 是一个介于 01 之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。

<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 }"
/>

它支持 hoverpressdragfocusinView

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 交互。但有时我们需要手动控制动画播放。

可以使用 useAnimatehook (钩子)来实现

  • 动画任何 HTML/SVG 元素(不仅仅是 motion 组件)。

  • 复杂的动画序列。

  • 使用 timespeedplay()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"

对于基础动画,你可以更新animate属性上的值:

<motion.div :animate="{ opacity: 1 }" />

当 animate 属性中的任何值发生更改时,组件将自动动画到新的目标值。

可动画的值

Motion 可以动画任何 CSS 值,甚至包括浏览器无法动画的值,例如 mask-image。它支持

  • 数字:0100 等。

  • 包含数字的字符串:"0vh""10px" 等。

  • 颜色:Hex、RGBA、HSLA。

  • 包含多个数字和/或颜色的复杂字符串(例如 box-shadow)。

  • display: "none"/"block"visibility: "hidden"/"visible"

值类型转换

通常,值只能在两种相同类型之间进行动画(例如,"0px""100px")。

颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。

此外,xywidthheighttopleftrightbottom 可以在不同的值类型之间动画。

<motion.div
  :initial='{ x: "100%" }'
  :animate='{ x: "calc(100vw - 50%)" }'
/>

也可以将 widthheight 动画到/出 "auto"

<motion.div
  :initial='{ height: "0px" }'
  :animate='{ height: "auto" }'
/>

注意:如果还要将 display 动画到/出 "none",请将其替换为 visibility "hidden",因为具有 display: none 的元素无法被测量。

Transforms (变换)

与 CSS 不同,Motion 可以独立地动画每个变换轴

  • Translate (位移):xyz

  • Scale (缩放):scalescaleXscaleY

  • Rotate (旋转):rotaterotateXrotateYrotateZ

  • Skew (倾斜):skewskewXskewY

  • 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 组件,xy 属性 可以使用 attrXattrY 设置。

Transform origin (变换原点)

transform-origin 具有三个快捷值,可以单独设置和动画

  • originX

  • originY

  • originZ

如果设置为数字,originXY 默认值为 01 之间的进度值。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 变量的值总是会触发重绘,因此使用 MotionValues来设置此类动画可能更高效。

CSS 变量作为动画目标

HTML motion 组件接受带有 CSS 变量的动画目标

<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />

SVG 线条绘制

可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLengthpathSpacingpathOffset

<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />

所有三个属性都设置为 01 之间的进度值,1 表示路径的总长度。

路径动画与 circleellipselinepathpolygonpolylinerect 元素兼容。

过渡

默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。

例如,像 xscale 这样的物理属性会使用弹簧物理效果进行动画,而像 opacitycolor 这样的值会使用基于持续时间的缓动曲线进行动画。

但是,你可以通过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 来将其用作初始关键帧。

这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。默认情况下,每个关键帧在整个动画中自然分布。你可以通过在 transition 中设置times (时间)选项来覆盖此设置。

times 是一个介于 01 之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。

<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 }"
/>

它支持 hoverpressdragfocusinView

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 交互。但有时我们需要手动控制动画播放。

可以使用 useAnimatehook (钩子)来实现

  • 动画任何 HTML/SVG 元素(不仅仅是 motion 组件)。

  • 复杂的动画序列。

  • 使用 timespeedplay()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"

对于基础动画,你可以更新animate属性上的值:

<motion.div :animate="{ opacity: 1 }" />

当 animate 属性中的任何值发生更改时,组件将自动动画到新的目标值。

可动画的值

Motion 可以动画任何 CSS 值,甚至包括浏览器无法动画的值,例如 mask-image。它支持

  • 数字:0100 等。

  • 包含数字的字符串:"0vh""10px" 等。

  • 颜色:Hex、RGBA、HSLA。

  • 包含多个数字和/或颜色的复杂字符串(例如 box-shadow)。

  • display: "none"/"block"visibility: "hidden"/"visible"

值类型转换

通常,值只能在两种相同类型之间进行动画(例如,"0px""100px")。

颜色可以在 hex、RGBA 和 HSLA 类型之间自由动画。

此外,xywidthheighttopleftrightbottom 可以在不同的值类型之间动画。

<motion.div
  :initial='{ x: "100%" }'
  :animate='{ x: "calc(100vw - 50%)" }'
/>

也可以将 widthheight 动画到/出 "auto"

<motion.div
  :initial='{ height: "0px" }'
  :animate='{ height: "auto" }'
/>

注意:如果还要将 display 动画到/出 "none",请将其替换为 visibility "hidden",因为具有 display: none 的元素无法被测量。

Transforms (变换)

与 CSS 不同,Motion 可以独立地动画每个变换轴

  • Translate (位移):xyz

  • Scale (缩放):scalescaleXscaleY

  • Rotate (旋转):rotaterotateXrotateYrotateZ

  • Skew (倾斜):skewskewXskewY

  • 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 组件,xy 属性 可以使用 attrXattrY 设置。

Transform origin (变换原点)

transform-origin 具有三个快捷值,可以单独设置和动画

  • originX

  • originY

  • originZ

如果设置为数字,originXY 默认值为 01 之间的进度值。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 变量的值总是会触发重绘,因此使用 MotionValues来设置此类动画可能更高效。

CSS 变量作为动画目标

HTML motion 组件接受带有 CSS 变量的动画目标

<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />

SVG 线条绘制

可以使用三个特殊属性通过许多不同的 SVG 元素创建线条绘制动画:pathLengthpathSpacingpathOffset

<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />

所有三个属性都设置为 01 之间的进度值,1 表示路径的总长度。

路径动画与 circleellipselinepathpolygonpolylinerect 元素兼容。

过渡

默认情况下,Motion 将基于被动画的值类型创建适当的过渡效果,以实现流畅的动画。

例如,像 xscale 这样的物理属性会使用弹簧物理效果进行动画,而像 opacitycolor 这样的值会使用基于持续时间的缓动曲线进行动画。

但是,你可以通过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 来将其用作初始关键帧。

这样,如果关键帧动画中断了另一个动画,则过渡会感觉更自然。默认情况下,每个关键帧在整个动画中自然分布。你可以通过在 transition 中设置times (时间)选项来覆盖此设置。

times 是一个介于 01 之间的进度值数组,用于定义每个关键帧在动画中应放置的位置。

<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 }"
/>

它支持 hoverpressdragfocusinView

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 交互。但有时我们需要手动控制动画播放。

可以使用 useAnimatehook (钩子)来实现

  • 动画任何 HTML/SVG 元素(不仅仅是 motion 组件)。

  • 复杂的动画序列。

  • 使用 timespeedplay()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

动画

示例

超越基础

Motion+是一次性付费,终身会员。

除了高级 Motion 功能、抢先体验内容和一个私密的 Discord 社区外,你还将解锁访问 90 多个高级示例的源代码的权限,这些示例将此页面上的 API 提升到一个新的水平。

加载中...
加载中...
保持联系

订阅以获取最新新闻和更新。

保持联系

订阅以获取最新新闻和更新。