暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Vue动画实现以及动画库的使用 animate.css,gsap库

刘先生的闲语 2022-08-26
1853

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class

  • 可以配合使用第三方 CSS 动画库,如 Animate.css

  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM

  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

vue 动画 (`transition`)

  1. 使用命名形式

<transition name="t" mode="out-in" appear>
  <h1 v-if="isShow">Hello World</h1>
</transition>
<style>
  .t-enter-active {
    animation: bounceInUp 1s ease-in-out;
  }
  .t-leave-active {
    animation: bounceOutDown 1s ease-in-out;
  }
</style>

  1. 使用加类名形式

<transition
  enter-active-class="animate__animated  animate__backInDown"
  leave-active-class="animate__animated animate__backOutDown dir"
>

  <h1 v-if="isShow">Hello LIUJUNJIE</h1>
</transition>

<style>
  .dir {
    animation-duration: reverse;
  }
</style>

transition 组件的生命周期钩子

<transition
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @before-leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
>

  <h1 v-if="isShow">Hello World</h1>
</transition>

不添加 css 动画

<transition :css="false">
  <h1 v-if="isShow">Hello World</h1>
</transition>

使用 animate.css

Animate.css | A cross-browser library of CSS animations.

npm install animate.css

可以使用添加类名的方式, 也可以使用动画形式如上列代码所示

使用 gsap

npm install gsap

<template>
  <div>
    <div>
      <button @click="isShow = !isShow">显示/隐藏</button>
    </div>
    <transition @enter="enter" @leave="leave">
      <h1 v-if="isShow">Hello World</h1>
    </transition>
  </div>
</template>

<script lang="ts" setup>
  import { ref } from "vue"
  import { gsap } from "gsap"

  const isShow = ref(true)

  const enter = (el: any, done: any) => {
    console.log("enter")
    gsap.from(el, {
      scale0,
      x200,
      y200,
      onComplete: done,
    })
  }

  const leave = (el: any, done: any) => {
    console.log("leave")
    gsap.to(el, {
      scale0,
      x200,
      y200,
      onComplete: done,
    })
  }
</script>

  • el 为动画对象

  • done 为动画结束调用

  • 其他属性可以详细查看 gsap

列表过度动画

  • 列表过度动画使用transition-group

  • 其他属性与transition
    相同

<template>
  <div>
    <input type="text" v-model="text" />
    <button @click="addItem">添加列表</button>
    <button @click="removeItem">删除列表</button>
    <ol>
      <transition-group name="item">
        <li class="item" v-for="(item, index) in list" :key="item">
          {{ item }}
        </li>
      </transition-group>
    </ol>
  </div>
</template>
<script setup lang="ts">
  import { reactive, ref } from "@vue/reactivity"
  let list = reactive(["hello world""吃饭""睡觉""打豆豆"])

  const text = ref("")

  const addItem = () => {
    let index = Math.round(Math.random() * (list.length - 1))
    list.splice(index, 0, text.value + list.length)
  }

  const removeItem = () => {
    let index = Math.round(Math.random() * (list.length - 1))
    list.splice(index, 1)
  }
</script>
<style>
  body {
    padding50px;
  }
  * {
    margin0;
    padding0;
  }
  input {
    font-size18px;
    padding10px;
  }
  .item {
    width100%;
    background-color#eeee;
    padding10px;
    border-radius10px;
    margin-top30px;
  }
  .item-enter-active {
    animation: lightSpeedInLeft 0.5s ease-in-out;
  }
  .item-leave-active {
    animation: lightSpeedInLeft 0.3s ease-in-out reverse;
    position: absolute;
    z-index1111;
  }
  .item-move {
    transition0.5s ease;
  }
</style>


动画列表1.gif

列表动画交替过度(解决一起添加或移除的生硬效果)

<template>
  <div>
    <input type="text" v-model="text" />
    <transition-group
      name="item"
      tag="ol"
      :css="false"
      @enter="enter"
      @leave="leave"
      @beforeEnter="beforeEnter"
    >

      <li
        class="item"
        v-for="(item, index) in showNames"
        :key="item"
        :data-index="index"
      >

        {{ item }}
      </li>
    </transition-group>
  </div>
</template>
<script setup lang="ts">
  import { reactive, ref, computed } from "@vue/reactivity"
  import gsap from "gsap"
  let list = reactive([
    "hello world",
    "吃饭",
    "睡觉",
    "打豆豆",
    "aaaaa",
    "刘俊杰",
    "刘俊杰",
    "刘小杰",
    "刘俊杰",
    "刘俊杰",
  ])

  const text = ref("")

  const showNames = computed(() => {
    return list.filter((item) => item.indexOf(text.value) !== -1)
  })

  const beforeEnter = (el) => {
    el.style.opacity = 0
    el.style.height = 0
  }

  const enter = (el, done) => {
    gsap.to(el, {
      opacity1,
      height"1.5em",
      delay: el.dataset.index * 0.1,
      onComplete: done,
    })
  }
  const leave = (el, done) => {
    gsap.to(el, {
      opacity0,
      height0,
      delay: el.dataset.index * 0.1,
      onComplete: done,
    })
  }
</script>
<style>
  body {
    padding50px;
  }
  * {
    margin0;
    padding0;
  }
  input {
    font-size18px;
    padding10px;
  }
  .item {
    width100%;
    background-color#eeee;
    padding10px;
    border-radius10px;
    margin-top30px;
  }
  .item-enter-active {
    animation: lightSpeedInLeft 0.5s ease-in-out;
  }
  .item-leave-active {
    animation: lightSpeedInLeft 0.3s ease-in-out reverse;
    position: absolute;
    z-index1111;
  }
  .item-move {
    transition0.5s ease;
  }
</style>

动画列表3.gif


文章转载自刘先生的闲语,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论