transition➕animation实现Vue动画

332 阅读5分钟

前言

在现代Web开发中,动画不仅能够提升用户界面的美观度,还能增强应用程序的交互性和响应性。Vue.js,作为一款流行的前端框架,提供了丰富的工具和方法来帮助开发者轻松地在项目中加入动画效果。本文将探讨Vue.js中处理动画的几种方式,包括CSS过渡、动画以及JavaScript控制的动画,并深入讲解Vue的内置<transition>组件如何简化这一过程。

transition组件

在Vue中,<transition>是一个内置组件,是用来给单个元素或组件添加进入/离开过渡效果的。它能够自动检测元素的匹配CSS过渡类并应用它们。<transition>组件提供了许多内置的类名来帮助你实现常见的过渡效果,同时也可以自定义过渡类名。

默认情况下,<transition>组件有以下的CSS类:

  • v-enter-from : 应用于元素开始进入的那一刻,在下一个帧移除。
  • v-enter-active: 应用于整个进入过渡过程,包含v-enter-to。可以用来定义过渡的时间曲线和持续时间。
  • v-enter-to 和 v-enter-active: 应用于元素结束进入的那一刻,在下一个帧移除。
  • v-leave-from : 应用于元素开始离开的那一刻,在下一个帧移除。
  • v-leave-active: 应用于整个离开过渡过程,包含v-leave-to
  • v-leave-to: 应用于元素结束离开的那一刻,在下一个帧移除。

.v-enter-from 和 .v-leave-to 表示过渡的起始状态。

.v-enter-active 和 .v-leave-active 在过渡过程中始终存在,可以用来定义过渡的持续时间和速度曲线。

.v-enter-to 和 .v-leave-from 则代表过渡的结束状态。

这段CSS样式用于定义Vue中的过渡效果,只涉及透明度的变化。

/* 进入时 */
.v-enter-from{
  opacity: 0;
}
.v-enter-active{
  transition: .3s;
}
.v-enter-to{
  opacity: 1;
}
/* 离开时 */
.v-leave-from{
  opacity: 1;
}
.v-leave-active{
  transition: 3s;
}
.v-leave-to{
  opacity: 0;
}

实现效果如下:

demo1.gif

这段CSS样式是用于定义一个带有滑动和淡入淡出效果的过渡动画,使用了transform实现位置的移动。

.slide-enter-from{
  opacity: 0;
  transform: translateX(30px);
}
.slide-enter-active{
  transition: .3s;
}
.slide-enter-to{
  opacity: 1;
}

.slide-leave-from{
  opacity: 1;
}
.slide-leave-active{
  transition: .3s;
}
.slide-leave-to{
  opacity: 0;
  transform: translateX(30px);
}

实现效果如下:

demo2.gif

这段CSS样式定义了一个名为 pulse 的关键帧动画,以及两个用于Vue.js过渡效果的类 .pulse-enter-active.pulse-leave-active

  1. 关键帧动画 @keyframes pulse:
    • 定义了从初始状态 (from) 到结束状态 (to) 的动画过程,其中在50%的时间点元素会放大到原始大小的1.5倍,然后恢复原状。
    • 使用 transform: scale3d() 函数可以确保动画在GPU上执行,从而提高性能。
  2. .pulse:
    • 将动画名称、持续时间和迭代次数应用于任何具有此类的元素。
    • animation-iteration-count: infinite; 表示动画将无限循环播放。
  3. 过渡效果类 .pulse-enter-active.pulse-leave-active:
    • 这些类被Vue.js过渡组件使用,以控制元素在进入和离开视图时的动画效果。因为它们都使用了 animation: pulse 1s;,所以元素在进入和离开时将显示相同的脉冲动画。
.pulse-enter-active{ animation: pulse 1s; } 
.pulse-leave-active{ animation: pulse 1s; } 
.pulse{ 
animation-name: pulse; 
animation-duration: 1s; 
animation-iteration-count: infinite; 
} 
/* css性能优化 性能渲染交给GPU加速 动画不要影响周围的文档流 */ 
@keyframes pulse{ 
from{ transform: scale3d(1,1,1); } 
50%{ transform: scale3d(1.5,1.5,1.5); } 
to{ transform: scale3d(1,1,1); } }

demo3.gif

完整代码:

<script setup>
import { ref } from 'vue';

const name = 'Ro9nin'
const isActive = ref(true);

</script>

<template>
  <div class="page">
    <div class="card">
      <div class="card__header">
        <h3 class="card-title">{{ name }}</h3>
        <div class="card-subtitle">Transition & Animation</div>
      </div>
      <div class="card__content">
          <!-- <transition name> -->
          <!-- <transition name="slide"> -->
         <transition name="pulse">
          <div v-if="isActive" class="emoji">⚡</div>
         </transition>
      </div>
      <div class="card__action"></div>
      <button type="button" @click="isActive = !isActive;">请按这里</button>
    </div>
  </div>
</template>

<style scoped>
@import './styles/app.css';
@import './styles/card.css';
@import './styles/animation.css';
</style>

CSS代码:

input[type='text'],
textarea,
select {
  padding: 4px 8px;
  margin: 8px 0;
  margin-right: 8px;
  font-size: 16px;
}

label {
  margin-left: 4px;
}
.page {
  padding: 32px;
  margin: 32px;
}

.emoji {
  font-size: 80px;
  transition: 0.5s;
}

.hidden {
  opacity: 0;
  transform: translateX(30px);
}

/* 进入时 */
.v-enter-from{
  opacity: 0;
}
.v-enter-active{
  transition: .3s;
}
.v-enter-to{
  opacity: 1;
}
/* 离开时 */
.v-leave-from{
  opacity: 1;
}
.v-leave-active{
  transition: 3s;
}
.v-leave-to{
  opacity: 0;
}

.slide-enter-from{
  opacity: 0;
  transform: translateX(30px);
}
.slide-enter-active{
  transition: .3s;
}
.slide-enter-to{
  opacity: 1;
}

.slide-leave-from{
  opacity: 1;
}
.slide-leave-active{
  transition: .3s;
}
.slide-leave-to{
  opacity: 0;
  transform: translateX(30px);
}


.pulse-enter-active{
  animation: pulse 1s;
}
.pulse-leave-active{
  animation: pulse 1s;
}
.card {
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: 300px;
    box-sizing: border-box;
    padding: 32px;
    margin: 0 auto;
    background: #f8f8f8;
    border-radius: 10px;
  }
  
  .card__header {
    text-align: center;
    margin-bottom: 32px;
  }
  
  .card-title {
    margin-bottom: 8px;
  }
  
  .card-subtitle {
    font-size: 12px;
    color: #989898;
  }
  
  .card__content {
    min-height: 250px;
  }
  
  .card__action > button {
    outline: none;
    border: none;
    background: none;
    border: 2px solid #000;
    padding: 10px 24px;
    cursor: pointer;
    margin: 4px;
  }
  
  .card__action > button:active {
    opacity: 0.8;
  }
.pulse{
    animation-name: pulse;
    animation-duration: 1s;
    animation-iteration-count: infinite;
}
/* css性能优化 性能渲染交给GPU加速 动画不要影响周围的文档流 */
@keyframes pulse{
    from{
        transform: scale3d(1,1,1);
    }
    50%{
        transform: scale3d(1.5,1.5,1.5);
    }
    to{
        transform: scale3d(1,1,1);
    }
}

高级动画库集成

对于复杂或专业级的动画效果,可以考虑集成如Animate.css这样的外部库。这些库提供了大量预设的动画效果,可以简单地通过类名应用到元素上。

Vue通过<transition>组件为CSS过渡和动画提供了一流的支持。当元素或组件在DOM中出现、消失或移动时,<transition>组件可以自动应用过渡效果。为了使用CSS过渡,你只需在元素上添加transition属性。

我们需要在终端命令行输入:

npm install animate.css

来安装Animate样式库。然后在全局入口文件main.js中通过

import 'animate.css'

来引入Animate样式库。