您的位置:

从多个方面详述Vue3动画

一、基础动画

1. 在Vue3中,动画是通过transition组件来实现的。transition组件提供了多个钩子函数,可以自定义动画的进入、离开等过渡效果。

2. 在transition组件中,可以使用`v-enter`和`v-leave`指令来定义动画进入和离开时的状态。同时也可以使用`v-enter-active`和`v-leave-active`来指定动画过渡时的状态。

3. 在动画过渡时,可以使用`.move`类名来定义动画效果的移动方向。


  <transition name="fade">
    <div v-if="show" class="show">Show Content</div>
  </transition>

  // CSS
  .fade-enter-active, .fade-leave-active {
    transition: opacity .3s ease-in-out;
  }
  .fade-enter, .fade-leave-to {
    opacity: 0;
  }

二、自定义动画

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. 在动画组中,可以使用`onBeforeEnter`、`onEnter`、`onAfterEnter`等钩子函数来定义元素的进入和退出方式。

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
  .list-enter-active, .list-leave-active {
    transition: transform .5s ease-in-out;
  }
  .move {
    transform: translateX(100%);
  }

四、复杂动画

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>