從多個方面詳述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>

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/192069.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-30 15:14
下一篇 2024-11-30 15:14

相關推薦

發表回復

登錄後才能評論