Vue 竟然能实现这么多动画效果

点击关注公众号,“技术干货” 及时达!

在现代的网页开发中,动画效果不仅能够增强用户体验,让网页变得更加生动和有趣,而且丰富的动画效果也是面试大厂的加分项。Vue.js 提供了强大的工具和内置组件,使得创建和管理动画效果变得更加简单和高效。在本文中,我们将详细介绍如何在 Vue 中使用动画,并提供一些最佳实践来帮助你编写高质量的动画代码。

页面动态效果

在 Vue 中实现动态效果有多种方法,包括 CSS 属性切换、animation 复杂的动画、JavaScript 样式操作以及 v-if/v-show 切换组件带来动画。下面我们将详细介绍这些方法。

CSS Transition 属性切换

CSS 的 transition 属性可以实现元素在不同状态之间平滑过渡。它是实现简单动画效果的理想选择。

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


const name = 'VUE动画';
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">
        <div :class="['emoji', { hidden: !isActive }]">🌲</div>
      </div>
      <div class="card__action">
        <button type="button" @click="isActive = !isActive;">请按这里</button>
      </div>
    </div>
  </div>
</template>


<style scoped>
/* 全局样式 */
@import './styles/app.css'; 
@import './styles/animation.css';
@import './styles/card.css';


.emoji {
  font-size: 80px;
  transition: 0.5s;
}
.hidden {
  opacity: 0;
  transform: translateX(30px);
}
</style>

在这个示例中,我们使用 transition 属性来实现动画效果。当点击按钮时,isActive 的值会切换,emoji 元素的类名也会随之改变,从而触发 CSS transition 动画。

277468496d6c05354d4b91a30f1bb492.jpeg

CSS Animation 属性

对于更复杂的动画效果,可以使用 CSS 的 animation 属性。通过定义关键帧,你可以实现复杂的动画序列。

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


const name = 'VUE动画';
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">
        <div :class="['emoji', { pulse: isActive }]">🌲</div>
      </div>
      <div class="card__action">
        <button type="button" @click="isActive = !isActive;">请按这里</button>
      </div>
    </div>
  </div>
</template>


<style scoped>
/* 全局样式 */
@import './styles/app.css'; 
@import './styles/animation.css';
@import './styles/card.css';


.emoji {
  font-size: 80px;
}


.pulse {
  animation: pulse 1s infinite;
}


@keyframes pulse {
  from {
    transform: scale3d(1, 1, 1);
  }
  50% {
    transform: scale3d(1.5, 1.5, 1.5);
  }
  to {
    transform: scale3d(1, 1, 1);
  }
}
</style>

在这个示例中,我们使用 CSS animation 属性实现了一个持续跳动的动画效果。pulse 类通过关键帧定义了动画序列,当 isActive 值改变时,emoji 元素的动画效果会被触发,实现scale 放大到1.5倍再复原的效果。

需注意这里的 scale3d 中的3d 它用于在三维空间中缩放元素。尽管在许多情况下可能只需要在二维空间中进行缩放,但使用 scale3d 具有一些性能优势,尤其是在利用 GPU 加速动画方面,使得动画不要影响周围的文档流。

4f2b0e4cd95ac373abd96aa4d49366fe.gif

Vue 提供的内置组件

Vue 提供了一些内置组件来帮助实现动画效果,其中最常用的是 transitionanimation

transition

<transition> 组件可以为单个元素/组件的进入和离开过程添加动画效果。

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


const name = 'VUE动画';
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 >
          <div v-if="isActive" class="emoji">🥹</div>
        </transition>
      </div>
      <div class="card__action">
        <button type="button" @click="isActive = !isActive;">请按这里</button>
      </div>
    </div>
  </div>
</template>


<style scoped>
/* 全局样式 */
@import './styles/app.css'; 
@import './styles/animation.css';
@import './styles/card.css';


.emoji {
  font-size: 80px;
}


./* 进入时 */
.v-enter-from{
  opacity: 0;
  


}


.v-enter-active{
 transition: .3s; 
}


.v-enter-to{
    opacity: 1;
}


/* 离开时 */


.v-leave-from{
    opacity: 1;
    
  
  }
  
  .v-leave-active{
   transition: 1s; 
  }
  
  .v-leave-to{
      opacity: 0;
  }
</style>

在这个示例中,我们使用了 Vue 的 <transition> 组件且用上了v-if,Vue 的 <transition> 组件通过一系列内置的生命周期钩子类名,使得动画的定制更加灵活和精细。这些钩子类名在元素进入和离开 DOM 时添加和移除,从而实现动画效果。

  • 进入阶段

    • .v-enter-from:在元素被插入之前被添加。代表进入动画的初始状态。

    • .v-enter-active:在元素被插入时立即被添加。定义进入动画的过渡属性,如 transitionanimation

    • .v-enter-to:在进入动画完成时被添加,移除 .v-enter-from。表示进入动画的最终状态。

  • 离开阶段

    • .v-leave-from:在元素被移除之前被添加。代表离开动画的初始状态。

    • .v-leave-active:在元素被移除时立即被添加。定义离开动画的过渡属性,如 transitionanimation

    • .v-leave-to:在离开动画完成时被添加,移除 .v-leave-from。表示离开动画的最终状态。

0c32615821b47f8c1a7df23f0ab14ff4.gif

除此之外我们还可以定制transition,直接给 transition 取一个name
<template>
            <transition name="pulse" >
              <div v-if="isActive" class="emoji">🥹</div>
          </transition>
        </template>
        
        <style scoped>
             .pulse-enter-active{
                animation: pulse 1s;
              }


              .pulse-leave-active{
                    animation: pulse 1s ;


              }
        </style>

且css定义 .name-enter-active.name-leave-active 这样也是可以达到效果的。

animation

我们也可以用上更为丰富的animate 库,里面封装了很多常见且更高级的动画效果,且使用起来非常方便。在这篇文章将以一个动画效果为例,讲述一下animate.css的简单使用。详细可以参考官方文档。Animate.css | A cross-browser library of CSS animations.

首先安装这个库的依赖
npm i animation.css
然后在main.js导入
import 'animate.css'
然后直接在 <transition> 组件中直接使用要添加效果的属性就行了。
<transition class="animate__tada"
            enter-active-class="animate__animated animate__tada"
            leave-active-class="animate__animated animate__bounce"
          >
          <div v-if="isActive" class="emoji">🥹</div>
          </transition>

其中 animate__tadaanimate__bounce是两种效果。

fb0b3906601790a78e4f006e7b727ac4.gif


良好的编程风格

最后还是要强调一下要培养一种良好的编程风格,这是进大厂的一个重要的加分项。

下面为完整的代码

<script setup>
  import {ref} from 'vue';
  // import {} from '';
  const name = 'VUE动画';
  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">
          <!-- <div :class="['emoji',{pulse: !isActive}]">🌲</div> -->
         
          <!-- <transition name="pulse" >
              <div v-if="isActive" class="emoji">🥹</div>
          </transition> -->
          
          <transition class="animate__tada"
            enter-active-class="animate__animated animate__tada"
            leave-active-class="animate__animated animate__bounce"
          >
          <div v-if="isActive" class="emoji">🥹</div>
          </transition>
        </div>
        <div class="card__action">
            <button type="button" @click="isActive =!isActive;">请按这里</button>
        </div>
      </div>
  </div>
 
</template>


<style scoped>
 /* 全局样式 */
  @import './styles/app.css'; 
  @import './styles/animation.css';
  @import './styles/card.css';
</style>

app.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: 1s; 
  }
  
  .v-leave-to{
      opacity: 0;
  }


  .slide-enter-from{
        opacity: 0;
        transform: translateX(30px);
  }


  .slide-enter-active{
        transition: .3s;
  }


  .slide-enter-to{
    opacity: 1;
    /* 默认会返回0 */
  }








  .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.css

.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;
  }

animation.css

.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);
    }
}

其中

<div class="card__header">
  <h3 class="card__title">{{ name }}</h3>
  <div class="card__subtitle">Transition & Animation</div>
</div>

使用了 BEM(Block Element Modifier)命名规范,使 CSS 类名更加语义化和层次分明。且将代码拆分成小的、可复用的组件有助于提高代码的可维护性和复用性。

编写清晰、简洁、语义化的 HTML 和 CSS 代码,可以提高网页的可读性和可维护性。

@import './styles/app.css';
@import './styles/animation.css';
@import './styles/card.css';

使用 @import 将 CSS 模块化,可以更好地组织和管理样式代码。

结语

通过这篇文章,我们学习了如何去使用CSS的动画属性和Vue的内置去实现动画的效果。熟悉掌握这些,我们可以创建出丰富多彩的动态效果,提升用户体验。在实际开发中,选择合适的动画实现方式,并遵循良好的编程规范,可以使我们的代码更加高效和易于维护!如果这篇文章对你有帮助,可以点个赞哦。

点击关注公众号,“技术干货” 及时达!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值