使用原生JS添加進(jìn)場(chǎng)和退場(chǎng)動(dòng)畫詳解
前言
總所周知啊,身為一個(gè)合格的前端搬磚工,會(huì)編寫并且添加一些基礎(chǔ)的動(dòng)畫效果可謂是比較基礎(chǔ)且輕車熟路的技能了。但是據(jù)我所見(jiàn),大部分的前端程序員其實(shí)只會(huì)添加進(jìn)場(chǎng)動(dòng)畫,而不知道如何添加退場(chǎng)動(dòng)畫。使用方式,也是簡(jiǎn)單粗暴的添加一個(gè)css類。
比如下面這種情況,增加一個(gè)下拉選項(xiàng)的展開(kāi)動(dòng)畫。我們會(huì)先準(zhǔn)備好keyframe關(guān)鍵幀和animation屬性的值。
.expand {
transform-origin: top;
animation: expand 0.3s ease both;
}
.fold {
transform-origin: top;
animation: fold 0.3s ease both;
}
/* 展開(kāi) */
@keyframes expand {
from {
transform: scaleY(0);
}
to {
transform: scaleY(1);
}
}
/* 折疊 */
@keyframes fold {
from {
transform: scaleY(1);
}
to {
transform: scaleY(0);
}
}使用的時(shí)候,就直接把這個(gè)類添加到目標(biāo)元素上面,呈現(xiàn)出來(lái)的效果就像這樣:

誠(chéng)然,這樣已經(jīng)基本上能夠滿足目前的絕大部分業(yè)務(wù)需求了,而且,絕大部分的客戶也不會(huì)注意到這個(gè)退場(chǎng)有沒(méi)有動(dòng)畫。但是,我作為一個(gè)比較喜歡鉆牛角尖的人,就特別想知道退場(chǎng)動(dòng)畫到底是怎么實(shí)現(xiàn)。不過(guò),由于我入行沒(méi)有多久,就趕上了vue普及開(kāi)來(lái)了的潮流,讓我一下子喪失了找尋這個(gè)問(wèn)題答案的興趣。
vue中的transition標(biāo)簽
自從工作中開(kāi)始使用了vue這個(gè)框架之后,媽媽再也不用擔(dān)心我不會(huì)添加退場(chǎng)動(dòng)畫了。在vue中,添加進(jìn)場(chǎng)和退場(chǎng)動(dòng)畫都變得非常的容易,只需要像下面這樣就行:
<transition enter-active-class="expand" leave-active-class="fold" appear>
<ul class="options-ul" v-show="isShow">
<li class="option">霧切之回光</li>
<li class="option">飛雷之弦振</li>
<li class="option">薙草之稻光</li>
<li class="option">波亂月白經(jīng)津</li>
</ul>
</transition>再后來(lái),等我可以比較熟練的應(yīng)對(duì)項(xiàng)目上的問(wèn)題的時(shí)候,我終于有閑情逸致可以探究一下究竟是怎么回事了。點(diǎn)開(kāi)DevTools,我發(fā)現(xiàn)在入場(chǎng)動(dòng)畫剛開(kāi)始執(zhí)行的時(shí)候,目標(biāo)元素上面會(huì)被添加上expand類,但是等到執(zhí)行完畢的時(shí)候,expand就被移除了。而執(zhí)行退場(chǎng)動(dòng)畫的時(shí)候,fold類會(huì)被添加到目標(biāo)元素上,等到退場(chǎng)動(dòng)畫結(jié)束的時(shí)候,fold類被移除,然后元素消失。
為此,我去了解了一下vue的transition標(biāo)簽的一些內(nèi)部原理。具體內(nèi)容參見(jiàn)我這篇文章——關(guān)于transition過(guò)渡動(dòng)畫的收獲;
簡(jiǎn)單說(shuō),就是我們要利用一個(gè)比較冷門的監(jiān)聽(tīng)事件animationend來(lái)監(jiān)聽(tīng)動(dòng)畫是何時(shí)執(zhí)行完畢的,然后再做下一步的處理。
小DEMO
根據(jù)這個(gè)思路,我們便可以寫出一個(gè)小DEMO。代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全原生樣式的下拉框</title>
</head>
<style>
html,
body {
margin: 0;
}
html{
--arrowSize: 8px;
}
div, ul {
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
background-color: #0B2550;
overflow: hidden;
}
#app {
width: 1000px;
height: 500px;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
border: 1px solid white;
position: relative;
margin: 100px auto;
background-color: #0B2550;
}
.selection-wrapper{
position: relative;
width: 250px;
height: 50px;
color: white;
margin: 20px auto;
font-size: 30px;
font-family: 華文楷體;
/*border: 1px solid #799cdc;*/
border-radius: 10px;
}
.displayText-box{
width: 100%;
height: 100%;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.displayText{
user-select: none;
}
.arrow-icon{
position: absolute;
top: 22px;
right: 10px;
width: 16px;
height: 8px;
line-height: initial;
font-size: 0;
transition: transform 0.3s ease;
}
.options-ul{
display: none;
width: 100%;
padding: 0;
margin: 0;
position: absolute;
top: 60px;
left: 0;
border: 2px solid #BDF0FF;
}
.option{
list-style: none;
text-align: center;
line-height: 40px;
cursor: default;
}
.expand {
transform-origin: top;
animation: expand 0.3s ease both;
}
.fold {
transform-origin: top;
animation: fold 0.3s ease both;
}
/* 展開(kāi) */
@keyframes expand {
from {
transform: scaleY(0);
}
to {
transform: scaleY(1);
}
}
/* 折疊 */
@keyframes fold {
from {
transform: scaleY(1);
}
to {
transform: scaleY(0);
}
}
</style>
<body>
<div id="app">
<h1 style="text-align: center;color: white;font-family: 華文楷體">選擇你想要的五星武器</h1>
<div class="selection-wrapper">
<div class="displayText-box">
<div class="displayText">請(qǐng)選擇</div>
<div class="arrow-icon">
<svg viewBox="0,0,16,8">
<path d="M 0,0 L 16,0 L 8,8 Z" fill="#31A1EF"></path>
</svg>
</div>
</div>
<ul class="options-ul expand">
<li class="option">霧切之回光</li>
<li class="option">飛雷之弦振</li>
<li class="option">薙草之稻光</li>
<li class="option">波亂月白經(jīng)津</li>
</ul>
</div>
</div>
</body>
<script>
const selection = document.querySelector('.displayText-box');
const ul = document.querySelector('.options-ul');
const arrow = document.querySelector('.arrow-icon');
selection.addEventListener('click',function (e){
let isExpand = ul.style.display === 'block';
if(isExpand){
// 折疊
ul.classList.add('fold');
arrow.style.transform = 'rotate(0deg)'
ul.onanimationend = function (){
ul.classList.remove('fold');
ul.style.display = 'none';
}
} else {
// 展開(kāi)
ul.style.display = 'block';
ul.classList.add('expand');
arrow.style.transform = 'rotate(180deg)'
ul.onanimationend = function (){
ul.classList.remove('expand');
}
}
})
</script>
</html>效果如下:

結(jié)語(yǔ)
這個(gè)DEMO就是一個(gè)最簡(jiǎn)單的退場(chǎng)動(dòng)畫的實(shí)現(xiàn)方式,即在animationend事件中使目標(biāo)元素消失。當(dāng)我們清楚原生的js是怎么寫的,那么在非vue環(huán)境中,我們也可以自由自在的添加各種各樣的退場(chǎng)動(dòng)畫了。不過(guò),有能力的小伙伴可能就直接去看vue的transition的源碼去了,而我這篇文章就是獻(xiàn)給像我一樣不想去看源碼但是還想知道一些旁門左道的知識(shí)的小伙伴。
到此這篇關(guān)于使用原生JS添加進(jìn)場(chǎng)和退場(chǎng)動(dòng)畫詳解的文章就介紹到這了,更多相關(guān)JS進(jìn)場(chǎng) 退場(chǎng)動(dòng)畫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript控制網(wǎng)頁(yè)平滑滾動(dòng)到指定元素位置的方法
這篇文章主要介紹了JavaScript控制網(wǎng)頁(yè)平滑滾動(dòng)到指定元素位置的方法,實(shí)例分析了javascript操作頁(yè)面滾動(dòng)的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
微信小程序?qū)崿F(xiàn)頂部選項(xiàng)卡(swiper)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)頂部選項(xiàng)卡效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
基于javascript實(shí)現(xiàn)最簡(jiǎn)單的選項(xiàng)卡切換效果
這篇文章主要介紹了基于javascript實(shí)現(xiàn)最簡(jiǎn)單的選項(xiàng)卡切換效果的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
解決js頁(yè)面滾動(dòng)效果scrollTop在FireFox與Chrome瀏覽器間的兼容問(wèn)題的方法
這篇文章為大家分享了解決js頁(yè)面滾動(dòng)效果scrollTop在FireFox與Chrome瀏覽器間的兼容問(wèn)題的方法,感興趣或者是遇到這種問(wèn)題的朋友可以參考這篇文章2015-12-12
28個(gè)JavaScript常用字符串方法以及使用技巧總結(jié)
這篇文章主要給大家介紹了28個(gè)JavaScript常用字符串方法以及使用技巧的相關(guān)資料,文中統(tǒng)計(jì)的方法都非常實(shí)用,無(wú)論是日常工作還是面試,都建議多看一看,需要的朋友可以參考下2021-09-09
跟我學(xué)習(xí)javascript的函數(shù)調(diào)用和構(gòu)造函數(shù)調(diào)用
跟我學(xué)習(xí)javascript的函數(shù)和構(gòu)造函數(shù)調(diào)用,主要包括三方面內(nèi)容函數(shù)調(diào)用、方法調(diào)用以及構(gòu)造函數(shù)調(diào)用,想要了解這些內(nèi)容的朋友千萬(wàn)不要錯(cuò)過(guò)下面的內(nèi)容。2015-11-11

