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

科技   2024-11-02 23:00   北京  

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群

在现代的网页开发中,动画效果不仅能够增强用户体验,让网页变得更加生动和有趣,而且丰富的动画效果也是面试大厂的加分项。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 动画。

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 加速动画方面,使得动画不要影响周围的文档流。

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。表示离开动画的最终状态。

除此之外我们还可以定制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是两种效果。


良好的编程风格

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

下面为完整的代码

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

Node 社群


我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。

   “分享、点赞在看” 支持一波👍

程序员成长指北
专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。
 最新文章