从多个方面详述Vue3动画

发布时间:2023-05-20

一、基础动画

  1. 在Vue3中,动画是通过transition组件来实现的。transition组件提供了多个钩子函数,可以自定义动画的进入、离开等过渡效果。
  2. 在transition组件中,可以使用v-enterv-leave指令来定义动画进入和离开时的状态。同时也可以使用v-enter-activev-leave-active来指定动画过渡时的状态。
  3. 在动画过渡时,可以使用.move类名来定义动画效果的移动方向。
<transition name="fade">
  <div v-if="show" class="show">Show Content</div>
</transition>
<!-- CSS -->
<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .3s ease-in-out;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

二、自定义动画

  1. Vue3通过defineAnimation函数来自定义动画。defineAnimation函数的参数包括:名称、函数、DOM元素引用和全局上下文。
  2. 在定义动画函数时,可以引入多个动画的步骤。这些动画步骤包括:enter、leave、delayEnter、delayLeave、orderEnter和orderLeave。
  3. 自定义动画的步骤中,开发者可以使用动画库如Tween.js等,来完成动画过渡效果并应用到DOM元素中去。
import { defineAnimation } from 'vue'
const myAnimation = defineAnimation({
  name: 'my-animation',
  setup: () => {
    return {
      onEnter(el, done) {
        anime({
          targets: el,
          opacity: [0, 1],  // 进入时元素从透明度0到1
          duration: 500,
          complete: () => {
            done();
          }
        });
      },
      onLeave(el, done) {
        anime({
          targets: el,
          opacity: [1, 0],  // 离开时元素从透明度1到0
          duration: 500,
          complete: () => {
            done();
          }
        });
      }
    }
  }
})
<!-- 在组件中使用 -->
<template>
  <div v-animation="myAnimation">
    Hello World
  </div>
</template>

三、多元素动画

  1. 在Vue3中,可以通过动画组使用多个元素的动画效果。动画组组件用于管理多个元素的动画效果,通过key的改变来触发元素的进入和离开。
  2. 在动画组中,可以使用onBeforeEnteronEnteronAfterEnter等钩子函数来定义元素的进入和退出方式。
  3. 在动画组中,可以使用moveClass属性来定义元素的移动方式。
<transition-group
  name="list"
  tag="ul"
  move-class="move"
>
  <li v-for="item in list" :key="item.id">
    {{ item.text }}
  </li>
</transition-group>
<!-- CSS -->
<style>
.list-enter-active, .list-leave-active {
  transition: transform .5s ease-in-out;
}
.move {
  transform: translateX(100%);
}
</style>

四、复杂动画

  1. 在Vue3中,可以通过transition组件和animate函数来实现复杂的动画效果。在animate函数中,可以通过执行多个动画步骤来实现动画的过渡效果。
  2. 在动画步骤中,可以使用动画库如GSAP等来实现复杂的动画效果。
<template>
  <transition
    name="complex"
    appear
    mode="out-in"
    @before-appear="beforeAppear"
    @appear="appear"
    @after-appear="afterAppear"
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
  >
    <div :key="selected.id">
      <h2>{{ selected.title }}</h2>
      <p>{{ selected.content }}</p>
    </div>
  </transition>
</template>
<script>
  import { ref } from 'vue'
  import animate from '@/utils/animate'
  export default {
    setup() {
      const selected = ref(null)
      const beforeAppear = (el) => {
        selected.value = { ...el.dataset }
        animate.set(el, { display: 'none' })
      }
      const appear = (el, done) => {
        animate.timeline()
          .set(el, { display: 'block' }, 0)
          .from(el.querySelector('h2'), {
            opacity: 0,
            x: -20,
            duration: 0.4
          }, 0.2)
          .from(el.querySelector('p'), {
            opacity: 0,
            x: -20,
            duration: 0.4,
            ease: 'power2.inOut'
          }, 0.4)
          .call(done)
      }
      const afterAppear = (el) => {
        animate.set(el.querySelector('h2, p'), { clearProps: 'all' })
      }
      const beforeEnter = (el) => {
        const next = el.dataset
        animate.set(el, { opacity: 0 })
        animate.timeline()
          .fromTo(el, {
            x: 100
          }, {
            x: 0,
            duration: 0.6,
            ease: 'power2.inOut'
          })
      }
      const enter = (el, done) => {
        animate.timeline()
          .fromTo(el, {
            opacity: 0
          }, {
            opacity: 1,
            duration: 0.6
          })
          .call(done)
      }
      const afterEnter = (el) => {
        animate.set(el, { clearProps: 'all' })
      }
      const beforeLeave = (el) => {
        const prev = selected.value
        animate.timeline()
          .fromTo(el, {
            opacity: 1
          }, {
            opacity: 0,
            duration: 0.6
          })
          .to(el, {
            x: -100,
            duration: 0.6,
            ease: 'power2.inOut'
          })
      }
      const leave = (el, done) => {
        animate.set(el, {
          opacity: 0
        })
        animate.timeline()
          .fromTo(el, {
            x: 0
          }, {
            x: -100,
            duration: 0.6,
            ease: 'power2.inOut'
          })
          .call(done)
      }
      const afterLeave = (el) => {
        animate.set(el, { clearProps: 'all' })
      }
      return {
        selected,
        beforeAppear,
        appear,
        afterAppear,
        beforeEnter,
        enter,
        afterEnter,
        beforeLeave,
        leave,
        afterLeave
      }
    }
  }
</script>