vue2.0 中使用transition實(shí)現(xiàn)動(dòng)畫效果使用心得
實(shí)踐
這里將通過四個(gè)實(shí)踐小案例來體驗(yàn)和學(xué)習(xí)css過渡,css動(dòng)畫,javascript鉤子,列表過渡的應(yīng)用。至于案例用到的知識(shí)點(diǎn)就請(qǐng)自行學(xué)習(xí)官網(wǎng)文檔。
1.css過渡–實(shí)踐
先來看看demo效果:

這個(gè)案例其實(shí)很簡(jiǎn)單,通過一個(gè)transition來觸發(fā)多個(gè)子元素的過渡效果,我們只需要定義元素對(duì)應(yīng)的過渡效果就可以,其他事情vue會(huì)幫我們搞定,由此可以擴(kuò)展出其他酷炫的過渡場(chǎng)景效果。先來看看這個(gè)簡(jiǎn)單案例的代碼實(shí)現(xiàn):
<template>
<div class="app">
<button @click="showMenu" class="btn">{{text}}</button>
<transition name="move">
<div class="menu" v-show="show">
<div class="inner inner-1">1</div>
<div class="inner inner-2">2</div>
<div class="inner inner-3">3</div>
</div>
</transition>
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
show: false
};
},
methods: {
showMenu () {
this.show = !this.show;
}
},
computed: {
text () {
return this.show ? '收' : '開';
}
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
.app
.btn
position: fixed
bottom: 50px
right: 10px
z-index: 10
width: 50px
height: 50px
line-height: 50px
border-radius: 50%
border: none
outline: none
color: #fff
font-size: 18px
background: blue
.menu
position: fixed
bottom: 50px
right: 10px
width: 50px
height: 50px
border-radius: 50%
transition: all .7s ease-in
&.move-enter-active
.inner
transform: translate3d(0, 0, 0)
transition-timing-function: cubic-bezier(0, .57, .44, 1.97)
.inner-1
transition-delay: .1s
.inner-2
transition-delay: .2s
.inner-3
transition-delay: .3s
&.move-enter, &.move-leave-active
.inner
transition-timing-function: ease-in-out
.inner-1
transform: translate3d(0, 60px, 0)
transition-delay: .3s
.inner-2
transform: translate3d(40px, 40px, 0)
transition-delay: .2s
.inner-3
transform: translate3d(60px, 0, 0)
transition-delay: .1s
.inner
display: inline-block
position: absolute
width: 30px
height: 30px
line-height: 30px
border-radius: 50%
background: red
text-align: center
color: #fff
transition: all .4s
.inner-1
top: -50px
left: 10px
.inner-2
left: -30px
top: -30px
.inner-3
left: -50px
top: 10px
</style>
可以看到我們的代碼基本主要是完成css過渡效果的樣式,而觸發(fā)過渡效果只是簡(jiǎn)單地通過一個(gè)click事件就搞定了,vue會(huì)自動(dòng)嗅探目標(biāo)元素是否有 CSS 過渡或動(dòng)畫,并在合適時(shí)添加/刪除 CSS 類名。那下一個(gè)demo就來簡(jiǎn)單實(shí)現(xiàn)一下使用css animation 做過渡的效果。
2.css 動(dòng)畫–實(shí)踐
先來看看demo效果:

這個(gè)案例其實(shí)跟上面的demo差不多,不同之處在于過渡效果是使用css動(dòng)畫來實(shí)現(xiàn),看下實(shí)現(xiàn)的代碼:
<template>
<div class="app">
<button @click="showball" class="btn">show</button>
<transition name="move" type="animation">
<div class="ball" v-show="show">
<div class="inner"></div>
</div>
</transition>
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
show: false
};
},
methods: {
showball () {
this.show = !this.show;
}
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
@keyframes shape-change {
0%, 100% {
border-radius: 50%
background: red
}
50% {
border-radius: 0
background: blue
}
}
@keyframes moveball-in {
0% {
transform: translate3d(300px,-200px,0)
}
50% {
transform: translate3d(100px,-400px,0)
}
100% {
transform: translate3d(0,0,0)
}
}
@keyframes moveball-out {
0% {
transform: translate3d(0,0,0)
}
50% {
transform: translate3d(100px,-400px,0)
}
100% {
transform: translate3d(300px,-200px,0)
}
}
.app
.btn
width: 40px
height: 30px
margin-top: 40px
border: none
outline: none
background: red
color: #fff
.ball
position: absolute
bottom: 20px
left: 20px
width: 50px
height: 50px
transition: all 1s cubic-bezier(.22,-0.86,.97,.58)
&.move-enter-active
opacity: 1
animation: moveball-in 1s
.inner
animation: shape-change 1s
&.move-leave-active
opacity: 0.8
animation: moveball-out 1s
.inner
animation: shape-change 1s
.inner
display: inline-block
width: 30px
height: 30px
border-radius: 50%
background: red
transition: all 1s linear
</style>
從css代碼可以看出,我們只是在vue過渡類名下加了不同的animation而已。官網(wǎng)文檔明確說明當(dāng)只使用transition或animation其中一種時(shí),vue是能自動(dòng)監(jiān)聽對(duì)應(yīng)的類型的,但是如果同一個(gè)元素同時(shí)使用兩種效果,就需要明確指定監(jiān)聽哪一種類型,不過官網(wǎng)并沒有給出具體的栗子。那其實(shí)這個(gè)demo已經(jīng)簡(jiǎn)單地實(shí)現(xiàn)同時(shí)使用兩種類型的情況,可以看到有一個(gè)透明度的變化。但是假如animation里使用了transform,并且外面也使用了transform的話,那么元素在過渡的時(shí)候動(dòng)畫效果就會(huì)有沖突,效果就有點(diǎn)出入了。
3.JavaScript鉤子 – 實(shí)踐
前兩個(gè)栗子都是有進(jìn)入和離開的過渡,但是如果一些場(chǎng)景只需要進(jìn)入過渡然后就結(jié)束了,那么這時(shí)就可以使用JavaScript鉤子結(jié)合CSS transitions/animations來實(shí)現(xiàn),當(dāng)然也可以單獨(dú)使用。看下demo:

這個(gè)一個(gè)非常low的模擬炮彈發(fā)射的場(chǎng)景,可以看到小球有拋物線軌跡運(yùn)動(dòng)的過渡,而且發(fā)射出去就不會(huì)再回來了,那么這個(gè)demo就是使用了JavaScript鉤子結(jié)合css來實(shí)現(xiàn)的,接下來看下關(guān)鍵代碼:
<template>
<div class="app">
<div class="gun" @click="launch($event)"></div>
<div class="shells-wrapper">
<transition v-for="shell in shells" name="launch-shell" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="shell" v-show="shell.show">
<div class="inner"></div>
</div>
</transition>
</div>
<div class="goal"></div>
<!--小球第二種-->
<div class="ball-container">
<ul>
<li v-for="(ball,index) in balls" :key="index">
<transition :css="false" name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
<div class="ball" v-show="ball.show">
<div class="inner inner-hook"></div>
</div>
</transition>
</li>
</ul>
</div>
<!--小球 End-->
</div>
</template>
首先,由于本身這個(gè)demo是一組元素的過渡,所以有些童鞋就會(huì)覺得用2.0提供的transition-group不就行了嘛。不過transition-group是列表過渡,我的理解是那一組元素是相關(guān)聯(lián)的、互相影響的,但是這個(gè)demo的元素每個(gè)都是獨(dú)立的,只不過是一組獨(dú)立的元素過渡,所以還是用transition比較合理,那使用v-for就可以實(shí)現(xiàn)一組相同過渡的元素啦。接下來看JavaScript鉤子怎么實(shí)現(xiàn)這個(gè)過渡:
export default {
data () {
return {
shells: [
{
show: false
},
{
show: false
},
{
show: false
}
]
};
},
methods: {
launch (event) {
for (let i = 0; i < this.shells.length; i++) {
let shell = this.shells[i];
if (!shell.show) {
shell.show = true;
shell.target = event.target;
return;
}
}
},
beforeEnter (el) {
let count = this.shells.length;
while (count--) {
let shell = this.shells[count];
if (shell.show) {
let rect = shell.target.getBoundingClientRect();
let left = rect.left - 32;
let top = -(window.innerHeight - rect.top - 15);
el.style.display = '';
el.style.webkitTransform = `translate3d(0,${top}px,0)`;
el.style.transform = `translate3d(0,${top}px,0)`;
let inner = el.getElementsByClassName('inner')[0];
inner.style.webkitTransform = `translate3d(${left}px,0,0)`;
inner.style.transform = `translate3d(${left}px,0,0)`;
}
}
},
enter (el, done) {
/* eslint-disable no-unused-vars */
let refresh = el.offsetHeight;
this.$nextTick(() => {
el.style.webkitTransform = 'translate3d(0,0,0)';
el.style.transform = 'translate3d(0,0,0)';
let inner = el.getElementsByClassName('inner')[0];
inner.style.webkitTransform = 'translate3d(0,0,0)';
inner.style.transform = 'translate3d(0,0,0)';
});
done();
},
afterEnter (el) {
let ball = this.shells[0];
ball.show = false;
el.style.display = 'none';
}
}
};
css樣式代碼:
.ball-container .ball position: absolute left: 32px bottom: 22px z-index: 50 transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41) .inner width: 16px height: 16px border-radius: 50% background: rgb(0, 160, 220) transition: all 0.4s linear
過渡元素就不需要為其添加vue的過渡css類名了,只需在元素本身添加transition即可,那vue在之前css過渡的時(shí)候會(huì)自動(dòng)幫我們?nèi)ヌ砑訉?duì)應(yīng)的類名來完成過渡效果,但是用javascript鉤子就需要我們自己完成這個(gè)始末狀態(tài)的設(shè)置了。當(dāng)我們點(diǎn)擊觸發(fā)一個(gè)過渡的時(shí)候,我們?cè)赽eforeEnter里先拿到當(dāng)前元素的偏移位置,然后給過渡元素設(shè)置其起始位置,在enter里需要重新觸發(fā)下瀏覽器的重繪,然后在下一幀重新設(shè)置元素的結(jié)束位置,這時(shí)就會(huì)產(chǎn)生過渡效果,在過渡完成后我們將當(dāng)前元素隱藏即可。那剛才講到的列表過渡,接下來就是關(guān)于使用transition-group的一個(gè)小demo了。
4.transition-group – 實(shí)踐
先看下demo效果:

其實(shí)就是個(gè)簡(jiǎn)單的todo lists的小demo,可以看到,當(dāng)其中一個(gè)元素過渡的時(shí)候,會(huì)影響其他元素的過渡。當(dāng)然,刪除按鈕其實(shí)本身也是一個(gè)transition過渡,也就是說可以在transition-group里使用transition,看下相關(guān)代碼:
<template>
<div class="app">
<button @click="add" class="add-btn">+</button>
<transition-group name="slide" tag="ul" class="list-wrapper">
<li class="list" v-for="(item, index) in lists" v-touch:swipeleft="showBtn.bind(this, index)" v-touch:swiperight="hideBtn.bind(this, index)" :key="item">
<span class="text">{{item.text}}</span>
<transition name="move">
<button class="del-btn" @click="delList(index)" v-show="item.show">刪除</button>
</transition>
</li>
</transition-group>
</div>
</template>
有個(gè)小坑的地方就是,之前看官網(wǎng)列表過渡的栗子,它是一個(gè)數(shù)組,元素都是數(shù)字,并且每一項(xiàng)都必須設(shè)置唯一的key值。所以我完成demo的時(shí)候就自作聰明地將索引值傳給key,結(jié)果過渡老是不對(duì),后來換成對(duì)應(yīng)的item就正常了(生無可戀臉)。這個(gè)demo用到了vue-touch,雖然github上說不支持2.0版本了,但是有一個(gè)next分支是支持的,只需在項(xiàng)目下安裝它即可:
sudo npm install --save git: //github.com/vuejs/vue-touch.git#next
這里看下主要的樣式:
.list display: flex width: 100% height: 40px line-height: 40px margin-bottom: 10px color: #666 font-size: 14px background: #eee transition: all .4s &.slide-move transition: transform 1s &.slide-enter transform: translate3d(-100%, 0, 0) &.slide-leave-active position: absolute transform: translate3d(-100%, 0, 0) &:last-child margin-bottom: 0 .del-btn flex: 0 0 60px border: none outline: none color: #fff background: red transition: all .4s &.move-enter, &.move-leave-active transform: translate3d(70px, 0, 0) .text flex: 1 padding-left: 20px
如果改變定位過渡的duration與進(jìn)入離開一樣的話,其實(shí)可以不用-move,這里設(shè)置-move的過渡的duration不同于元素進(jìn)入離開的duration產(chǎn)生一種速度差,看起來舒服點(diǎn)。而且-leave-active需要設(shè)置position: absolute才會(huì)有效果。現(xiàn)在看來其實(shí)列表過渡也是很容易實(shí)現(xiàn)的。
ps:下面看下vue.js 2.* 使用transition實(shí)現(xiàn)動(dòng)畫效果
<transition name="fade">
<div class="detail" v-show="detailShow"></div>
</transition>
<script type="text/ecmascript-6">
export default {
};
</script>
<style lang="stylus" ref="sheetstyle/stylus">
.fade-enter-active, .fade-leave-active
opacity:1
transition: all 1.0s
background:rgba(7,17,27,0.8)
.fade-enter, .fade-leave-active
opacity: 0
background:rgba(7,17,27,0)
</style>
總結(jié)
以上所述是小編給大家介紹的vue2.0 中使用transition實(shí)現(xiàn)動(dòng)畫效果使用心得,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Vue 簡(jiǎn)單實(shí)現(xiàn)前端權(quán)限控制的示例
這篇文章主要介紹了Vue 簡(jiǎn)單實(shí)現(xiàn)前端權(quán)限控制的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Vue3管理后臺(tái)項(xiàng)目使用高德地圖選點(diǎn)的實(shí)現(xiàn)
本文主要介紹了Vue3管理后臺(tái)項(xiàng)目使用高德地圖選點(diǎn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
vue3+ts+vite2項(xiàng)目實(shí)戰(zhàn)踩坑記錄
最近嘗試上手Vue3+TS+Vite,對(duì)比起Vue2有些不適應(yīng),但還是真香,下面這篇文章主要給大家介紹了關(guān)于vue3+ts+vite2項(xiàng)目的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
Vue中Video標(biāo)簽播放解析后短視頻去水印無響應(yīng)解決
這篇文章主要為大家介紹了Vue中使用Video標(biāo)簽播放?<解析后的短視頻>去水印視頻無響應(yīng)的解決方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
vue+swiper實(shí)現(xiàn)組件化開發(fā)的實(shí)例代碼
這篇文章主要介紹了vue+swiper實(shí)現(xiàn)組件化開發(fā)的相關(guān)資料,需要的朋友可以參考下2017-10-10
對(duì) Vue-Router 進(jìn)行單元測(cè)試的方法
這篇文章主要介紹了對(duì) Vue-Router 進(jìn)行單元測(cè)試的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
vue實(shí)現(xiàn)下拉框二級(jí)聯(lián)動(dòng)效果的實(shí)例代碼
這篇文章主要介紹了vue實(shí)現(xiàn)下拉框二級(jí)聯(lián)動(dòng)效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11

