likes
comments
collection
share

🥚第三库动画与框架的结合

作者站长头像
站长
· 阅读数 37

Vue3过渡动画


1.认识动画

  • 在开发中,如果我们要给一个组件的显示和消失添加动画,就可以增加用户体验

    • React是没有提供任何动画相关的API,但是vue中给我们提供好了一些内置的组件和对应的API来完成动画,利用它们我们可以方便的实现过渡动画效果

    • 没有动画的情况下,整个内容的显示和隐藏会非常的生硬:

🥚第三库动画与框架的结合

    -   如果我们希望给单元素或者组件实现过渡动画,可以使用 transition 内置组件来完成动画;

-   下面我们通过一个小案例来开始学习
  • App.vue
<template>
  <div>
    <button @click="isShow = !isShow">显示|隐藏</button>
    <transition name="fade">
      <h2 v-if="isShow">App.vue</h2>
    </transition>
  </div>
</template>
<script>
  export default {
    data() {
     return {
       isShow:true
     } 
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      }
    }
  }
</script>
<style scoped>
  .fade-enter-from,
  .fade-leave-to {
    opacity:0;
  }
  .fade-enter-to,
  .fade-leave-from {
    opacity:1
  }
  
  .fade-enter-active,
  .fade-leave-active{
    transition: all 0.5s ease;
  }
</style>

2.Transition组件原理

  • 我们会发现,Vue自动给h2元素添加了动画,这是啥原因呢
  • 当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
  1. 会自动探测目标元素是否应用了CSS过度或动画,如果有就在恰当时机添加/删除CSS类名;
  2. 如果tansition 组件提供了JS钩子函数,这些钩子函数将在恰当的时机被调用
  3. 如果没有找到JS钩子并且没有检测到CSS过度|动画,DOM插入,删除操作将会立即执行;

3.过渡动画class

  • 我们会发现上面提到了很多个class,Vue就是帮助我们在这些class之间来回切换完成的动画
  • v-enter-from:定义进入过渡的开始状态,在元素被插入之前生效,在元素被插入之后的的下一帧移除
  • v-enter-active:定义进入过渡生效时的状态,在整个进入过渡的阶段中应用,在元素被插入之前生效, 在过渡或者动画完成之后移除,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
  • v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡/ 动画完成之后移除。
  • v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除
  • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  • v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被删除),在过渡/ 动画完成之后移除。

🥚第三库动画与框架的结合


4.animation动画

不多说,直接上代码,其实就是换成了动画,还是一个样样🉐️

<template>
  <button @click="isShow=isShow">
    显示|隐藏
  </button>
  <transition name="fade">
    <h2 v-if="isShow">放大🐸</h2>
  </transition>
</template>
<script>
    export default {
      data() {
        return {
          isShow:true
        }
      }
    }
</script>
<style scoped>
  .fade-enter-active {
    animation:bounce 0.5s ease;
  }
  .fade-leave-active {
    animation bounce 0.5s ease reverse;
  }
  
  @keyframes bounce {
    0% {
      transform:scale(0)
    }
    50% {
      transform:scale(1.5)
    }
    100% {
      transform:scale(1)
    }
  }
</style>

5.同时设置过渡和动画

  • Vue为了知道过渡的完成,内部是在监听transitionend或animationend,到底使用那个取决于元素应用的规则

    • 如果知识使用了其中一个,那么Vue能自动识别类型并设置监听
  • 但如果同时使用会怎么样呢?

    • 在这种情况下可能某一个动画执行结束时,另一个动画还没有结束
    • 我们可以设置type属性为 animation 或者 transition来明确告知Vue监听的类型
  • 👀以下代码示例:

<template>
  <button @click="isShow=isShow">
    显示|隐藏
  </button>
  <!-- 一般不会遇到这玩意,同时使用非常少,如果有也是设置type=时间动画长的那个 -->
  <!-- 
  duration第一种写法:duration="1000"
  duration第二种写法:duration= {enter:800,leave:1000}
  也是很少使用,但是要知道有这个属性
  -->
  <transition name="fade" type="animation" :duration="1000">
    <h2 v-if="isShow">放大🐸</h2>
  </transition>
</template>
<script>
    export default {
      data() {
        return {
          isShow:true
        }
      }
    }
</script>
<style scoped>
  .fade-enter-from,
  .fade-leave-to {
    opacity:0;
  }
  
  .fade-enter-active,
  .fade-leave-active {
    transition:opacity 0.5s ease;
  }
  
  
  
  .fade-enter-active {
    animation:bounce 0.5s ease;
  }
  .fade-leave-active {
    animation bounce 0.5s ease reverse;
  }
  
  @keyframes bounce {
    0% {
      transform:scale(0)
    }
    50% {
      transform:scale(1.5)
    }
    100% {
      transform:scale(1)
    }
  }
</style>

6.过渡模式

还是先从一段代码看起然后进行分析

<template>
  <button @click="isShow=isShow">
    显示|隐藏
  </button>
  <transition name="fade" mode="in-out">
    <h2 v-if="isShow">放大🐸</h2>
    <h2 v-else>井底之蛙,土黑娃</h2>
  </transition>
</template>
<script>
    export default {
      data() {
        return {
          isShow:true
        }
      }
    }
</script>
<style scoped>
  .fade-enter-from,
  .fade-leave-to {
    opacity:0;
  }
  
  .fade-enter-active,
  .fade-leave-active {
    transition:opacity 0.5s ease;
  }
  
  
  
  .fade-enter-active {
    animation:bounce 0.5s ease;
  }
  .fade-leave-active {
    animation bounce 0.5s ease reverse;
  }
  
  @keyframes bounce {
    0% {
      transform:scale(0)
    }
    50% {
      transform:scale(1.5)
    }
    100% {
      transform:scale(1)
    }
  }
</style>

解释如下:

  • 我们运行程序之后会发现一个问题:放大🐸 和 井底之蛙,土黑娃 是同时存在的

    • 这是因为默认情况下进入和离开动画是同时发生的
  • 但是我们不希望这么做,则需要设置transition得过渡模式:

    • in-out:新元素先进行过渡,完成后当前元素过渡离开
    • out-in:当前元素先进行过渡,完成后新元素过渡进入

还有一个点就是开发不仅仅是简单的标签切换,也有可能是组件的切换也可以使用过渡动画来进行包裹实现,我这里就不放代码了,如果有兴趣可以直接去这篇文章juejin.cn/post/715842…找到对应的动态组件代码结合本篇文章进行使用。还有如果appear设置了就代表默认就执行动画代码。意思就是一开始就执行动画

🥚第三库动画与框架的结合

[注意⚠️​]  isShow? 'home' : 'about' 是对应的组件!(可以创建试试看哦)


7.animate.css

  • 为什么要使用第三方库呢?不是已经有内置好的动画组件了?

    • 其实🤔,使用内置的也可以,但是在开发阶段肯定是以效率为主,所以引用一些第三方库的动画库,比如animate.css,点我进入官网
  • 那么什么是animate.css?

    • Animate.css is a library of ready-to-use, cross-browser animations for use in your web projects. Great for emphasis, home pages, sliders, and attention-guiding hints.
  • 如何使用这个库呢?

  • 安装animate.css库
  • 导入animate.css库的样式
  • 使用animation动画或者animate提供的类
#安装
npm install animate.css --save
//在全局导入这个库的样式
import 'animate.css';

第一种方式1️⃣

<template>
  <div class="app">
  <button @click="isShow = !isShow">显示/隐藏</button>
    
  <transition name="fade">
    <h2 v-show="isShow">Animate.css</h2>
  </transition>
  </div>
</template><script>
  export default {
    data() {
      return {
        isShow: true
      }
    }
  }
</script><style scoped>
  .fade-enter-active{
    animation:fadeInRightBig 1s ease-in;
  }
  .fade-leave-active {
    animation:fadeInRightBig 1s ease-in reverse;
  }
</style>

第二种方式2️⃣:自定义过渡class

  • 我们可以通过以下 attribute 来自定义过渡类名:

    • enter-from-class
    • enter-active-class
    • enter-to-class
    • leave-from-class
    • leave-active-class
    • leave-to-class
  • 优先级高于普通的类名,这对于Vue的过渡系统和其他第三方css动画库,比如Animate.css结合使用

<template>
  <div class="app">
  <button @click="isShow = !isShow">显示/隐藏</button>
  <!-- 这个就是使用自定义的class然后去官网复制对应的类粘贴在
这些自定义类里面就可以实现进入 或者出去 的动画效果-->
  <!-- 还有这个animate_animated必须加上才会有效果 -->
  <transition enter-active-class="animate__animated animate__bounce">
    <h2 v-show="isShow">Animate.css</h2>
  </transition>
  </div>
</template><script>
  export default {
    data() {
      return {
        isShow: true
      }
    }
  }
</script>
<style scoped></style>

8.JavaScript钩子

  • 在使用动画之前,我们先来看一下transition组件给我们提供的JavaScript钩子,这些钩子可以帮助我们监听动画执行到什么阶段了
  • 当我们使用JS来执行过渡动画时,需要进行done回调,否则将会被同步调用,过渡会立即完成
  • 添加:css="false",也会让Vue跳过css的jian ce,除了性能略高之外,这可以有效避免过渡中css规则的影响
  • 意思就是说执行对应的动画的时候,比如from to这些就对应着beforeenter,beforeleave
  • 通过下面👇这段代码进行查看
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
​
    <transition @before-enter="beforeEnter"
                @enter="enter"
                @after-enter="afterEnter"
                @enter-cancelled="enterCancelled"
                @before-leave="beforeLeave"
                @leave="leave"
                @afterLeave="afterLeave"
                @leave-cancelled="leaveCancelled"
                :css="false">
      <h2 class="title" v-if="isShow">Hello World</h2>
    </transition>
  </div>
</template><script>
  export default {
    data() {
      return {
        isShow: true
      }
    },
    methods: {
      beforeEnter() {
        console.log("beforeEnter");
      },
      enter() {
        console.log("enter");
      },
      afterEnter() {
        console.log("afterEnter");
      },
      enterCacelled() {
        console.log("enterCacelled")
      },
      beforeLeave() {
        console.log("beforeLeave");
      },
      leave() {
        console.log("leave");
      },
      afterLeave() {
        console.log("afterLeave");
      }
      leaveCancelled() {
        console.log("leaveCancelled")
      }
    }
  }
</script><style scoped>
  .title {
    display: inline-block;
  }
</style>

9.gsap库

  • 什么是gsap呢? 点击我进官网

    • GSAP就是 GreenSock动画平台
    • 非常强大,通过javascript给css属性,SVG,Canvas等设置动画,而且浏览器兼容的
  • 如何使用这个库?

    1. 安装gsap
    2. 导入gsap库
    3. 使用提供的API
#安装gsap
npm install gsap
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
​
    <transition @enter="enter"
                @leave="leave"
                :css="false">
      <h2 class="title" v-if="isShow">Hello World</h2>
    </transition>
  </div>
</template><script>
  import gsap from 'gsap';
​
  export default {
    data() {
      return {
        isShow: true,
      }
    },
    methods: {
      enter(el, done) {
        console.log("enter");
        gsap.from(el, {
          scale: 0,
          x: 200,
          onComplete: done
        })
      },
      leave(el, done) {
        console.log("leave");
        gsap.to(el, {
          scale: 0,
          x: 200,
          onComplete: done
        })
      }
    }
  }
</script><style scoped>
  .title {
    display: inline-block;
  }
</style>

9.1小案例

  • 这个案例就是让数字一点点变化
<template>
  <div class="app">
    <input type="number" step="100" v-model="counter">
    <h2>当前计数: {{showNumber.toFixed(0)}}</h2>
  </div>
</template><script>
  import gsap from 'gsap';
​
  export default {
    data() {
      return {
        counter: 0,
        showNumber: 0
      }
    },
    watch: {
      counter(newValue) {
        gsap.to(this, {duration: 1, showNumber: newValue})
      }
    }
  }
</script><style scoped>
</style>

10.认识列表过渡transition-group

    • 默认情况下,它不会渲染一个元素的包裹器,但是你可以指定一个元素并以 tag attribute 进行渲染;
    • 过渡模式不可用,因为我们不再相互切换特有的元素;
    • 内部元素总是需要提供唯一的 key attribute 值;
    • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身;
<template>
  <button @click="addNum">添加数字</button>
  <button @click="removeNum">删除数字</button>
  <button @click="shuffleNum">数字洗牌</button><transition-group tag="p" name="fade">
      <span v-for="item in numbers" :key="item" class="item">
        {{item}}
      </span>
  </transition-group>
</template>
<script>
  import _ from 'lodash';
  export default {
    data() {
      return {
        numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        numCounter: 10
      }
    },
    methods: {
      //随机位置添加
      addNum() {
        this.numbers.splice(this.randomIndex(),0,this.numCounter++)
      },
      //随机位置删除
      removeNum() {
        this.numbers.splice(this.randomIndex(),1)
      },
      //洗牌
      shuffleNum() {
        this.numbers = _.shuffle(this.numbers);
      },
      //随机值
      randomIndex() {
        return Math.floor(Math.random() * this.numbers.length)
      }
    }
  }
</script>
<style scoped>
 .item {
    margin-right: 10px;
    display: inline-block;
  }
  .fade-enter-from,
  .fade-leave-to {
    opacity:0
    transform:translateY(30px)
  }
  
  .fade-enter-active,
  .fade-leave-active {
    transition:all 1s
  }
  /* 添加离场为绝对定位,防止离场动画bug */
  .fade-leave-active {
    position:absolute;
  }
  /* 以通过使用一个新增的 v-move 的class来完成移动动画 */
  .fade-move {
    transition:transform 1s ease;
  }
</style>

10.1列表交替过渡案例

  • 我们来通过gsap的延迟delay属性,做一个交替消失的动画:
<template>
  <div>
    <input v-model="keyword">
    <transition-group tag="ul" name="fade" :css="false"
                      @before-enter="beforeEnter"
                      @enter="enter"
                      @leave="leave">
      <li v-for="(item, index) in showNames" :key="item" :data-index="index">
        {{item}}
      </li>
    </transition-group>
  </div>
</template><script>
  import gsap from 'gsap';
​
  export default {
    data() {
      return {
        names: ["abc", "cba", "nba", "why", "lilei", "hmm", "kobe", "james"],
        keyword: ""
      }
    },
    computed: {
      showNames() {
        return this.names.filter(item => item.indexOf(this.keyword) !== -1)
      }
    },
    methods: {
      beforeEnter(el) {
        el.style.opacity = 0;
        el.style.height = 0;
      },
      enter(el, done) {
        gsap.to(el, {
          opacity: 1,
          height: "1.5em",
          delay: el.dataset.index * 0.5,
          onComplete: done
        })
      },
      leave(el, done) {
        gsap.to(el, {
          opacity: 0,
          height: 0,
          delay: el.dataset.index * 0.5,
          onComplete: done
        })
      }
    }
  }
</script><style scoped>
  /* .fade-enter-from,
  .fade-leave-to {
    opacity: 0;
  }
​
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 1s ease;
  } */
</style>

11.做个小总结

  • 这篇文章主要讲了Vue动画组件还有一些第三方的动画库配合使用
  • 比如gsap和animate.css都可以实现一些动画效果吸引眼球
  • 还有transition-group,和transition组件一些小细节
转载自:https://juejin.cn/post/7158777076839874568
评论
请登录