本著想學(xué)習(xí)寫自定義指令的初衷犀勒,當(dāng)遇到這個(gè)需求時(shí)摔笤,便想以此為契機(jī)寫一個(gè)v-carousel的指令副女,來實(shí)現(xiàn)輪播圖的效果蛤高。后來發(fā)現(xiàn),用vue自帶的“過渡&動(dòng)畫”就能夠基本實(shí)現(xiàn)碑幅。
過渡動(dòng)畫的實(shí)現(xiàn)依靠vue封裝的兩個(gè)組件:
- 單元素/單組件/多元素/多組件過渡(單個(gè)節(jié)點(diǎn)或同一時(shí)間渲染多個(gè)節(jié)點(diǎn)中的一個(gè))戴陡,<transition></transtion>。
- 列表過渡沟涨,<transition-group></transition-group>恤批。考慮到我們是實(shí)現(xiàn)多個(gè)圖片的輪播裹赴,可以跳過直接看 => 列表過渡
其實(shí)喜庞,用vue內(nèi)置組件實(shí)現(xiàn)輪播圖效果很簡(jiǎn)單,思路是根據(jù)圖片的索引(idx)用v-show來進(jìn)行控制顯示和隱藏棋返。相比于往常通過控制外層ul元素的translateX值來達(dá)到輪播效果赋荆,它只通過當(dāng)前顯示的和即將顯示的兩個(gè)元素的translateX值來實(shí)現(xiàn)。
實(shí)現(xiàn)這個(gè)“輪播”效果的關(guān)鍵在于理解transition組件內(nèi)部css過渡類名的含義懊昨,并為其書寫相應(yīng)的css。
過渡的類名
在進(jìn)入/離開的過渡中春宣,會(huì)有 6 個(gè) class 切換酵颁。常用的是v-enter, v-enter-active, v-leave, v-leave-active這四個(gè)。其中"v"可以被自定義的name取代月帝。
v-enter:定義進(jìn)入過渡的開始狀態(tài)躏惋。在元素被插入之前生效,在元素被插入之后的下一幀移除嚷辅。
v-enter-active:定義進(jìn)入過渡生效時(shí)的狀態(tài)簿姨。在整個(gè)進(jìn)入過渡的階段中應(yīng)用,在元素被插入之前生效簸搞,在過渡/動(dòng)畫完成之后移除扁位。這個(gè)類可以被用來定義進(jìn)入過渡的過程時(shí)間,延遲和曲線函數(shù)趁俊。
v-enter-to: 2.1.8版及以上 定義進(jìn)入過渡的結(jié)束狀態(tài)域仇。在元素被插入之后下一幀生效 (與此同時(shí) v-enter 被移除),在過渡/動(dòng)畫完成之后移除寺擂。
v-leave: 定義離開過渡的開始狀態(tài)暇务。在離開過渡被觸發(fā)時(shí)立刻生效泼掠,下一幀被移除。
v-leave-active:定義離開過渡生效時(shí)的狀態(tài)垦细。在整個(gè)離開過渡的階段中應(yīng)用择镇,在離開過渡被觸發(fā)時(shí)立刻生效,在過渡/動(dòng)畫完成之后移除括改。這個(gè)類可以被用來定義離開過渡的過程時(shí)間腻豌,延遲和曲線函數(shù)。
v-leave-to: 2.1.8版及以上 定義離開過渡的結(jié)束狀態(tài)叹谁。在離開過渡被觸發(fā)之后下一幀生效 (與此同時(shí) v-leave 被刪除)饲梭,在過渡/動(dòng)畫完成之后移除。
在我們實(shí)現(xiàn)(自右向左)輪播的效果中焰檩,對(duì)應(yīng)css類名的css規(guī)則如下:
/* 注意順序不能錯(cuò)亂憔涉,-active的類名要配置在-enter類名之前 */
.carousel-enter-active {
transform: translateX(0);
transition: all 1s ease-in-out;
}
.carousel-leave-active {
transform: translateX(-100%);
transition: all 1s ease-in-out;
}
.carousel-enter {
transform: translateX(100%)
}
.carousel-leave {
transform: translateX(0)
}
//另外,li要添加position:absolute這個(gè)屬性析苫,它相對(duì)于carousel絕對(duì)定位兜叨。
對(duì)應(yīng)的html結(jié)構(gòu):
<transition-group tag="ul" name="carousel">
<li v-for="(item, idx) in mybanner" :key="idx" v-show="idx===mark">
<a href="" class="bannera">
<img :src="item.banner" alt="">
</a>
</li>
</transition-group>
<div class="bullet">
<span v-for='(item,idx) in mybanner.length' :class="{'active':idx===mark}" @click='change(index)'></span>
</div>
邏輯處理:
methods: {
change(i) {
this.mark = i
},
autoPlay() {
this.mark++
if (this.mark === this.len) { //len在data中定義了,為banner的個(gè)數(shù)
this.mark = 0
return
}
},
play() {
setInterval(this.autoPlay, 3000)
}
}
至此衩侥,結(jié)合vue內(nèi)置組件<transition-group>實(shí)現(xiàn)圖片輪播的過渡效果基本完成国旷。用 transition系列 實(shí)現(xiàn)過渡效果,代碼量較少茫死,對(duì)于不復(fù)雜的需求可以輕松實(shí)現(xiàn)跪但。
然而,若需要實(shí)現(xiàn)手指滑動(dòng)-->圖片輪播這種效果峦萎,單靠這個(gè)組件沒有辦法實(shí)現(xiàn)屡久;另外,圖片總是從右向左出現(xiàn)爱榔,不論是自動(dòng)循環(huán)被环,還是點(diǎn)擊了某張圖,過渡效果是一樣的详幽,因?yàn)閑nter-active,leave-active樣式是固定的筛欢。這不符合當(dāng)我們點(diǎn)擊某一張之前的圖片,希望它從左往右出現(xiàn)的視覺邏輯唇聘。
于此版姑,我們可以嘗試手寫一個(gè)vue輪播圖指令。
第一版蹩腳的嘗試??迟郎,思路還是老舊的那種(不同于上面)漠酿,“輪播”主要是通過改變外層ul元素的translateX值來達(dá)到效果:
directives: {
carousel: {
bind: function (el, binding, vnode, oldVnode) {
el.classList.add('flex', 'transition');
el.style.transform = 'translateX(-750px)'; // 初始化
let w = parseInt(el.style.width);
let n = Number(w/750), m = 1;
// 向左輪播
const carousel = function () {
if (m == n) {
el.style.transform = 'translateX(-750px)';
el.classList.remove('transition');
m = 1;
} else if (m == 0) {
el.style.transform = 'translateX(' + -750 * (n-1) + 'px)';
el.classList.remove('transition');
m = n-1;
} else {
el.classList.add('transition');
el.style.transform = 'translateX(' + -750 * (m) + 'px)';
m++;
}
}
setInterval(()=>{
carousel()
}, 3000)
}
}
}
.flex {
display: flex;
}
.transition {
transition: transform .5s linear;
}
<ul :style="{width: ULwidth + 'px'}" v-carousel>
<li v-for="(item, idx) in mybanner" v-if="idx === (mybanner.length - 1)">
<a class="bannera" href="" :data-form="item.form" :data-actCode="item.actCode">
<img :src="item.banner" alt="">
</a>
</li>
<li v-for="(item, idx) in mybanner">
<a class="bannera" href="" :data-form="item.form" :data-actCode="item.actCode">
<img :src="item.banner" alt="">
</a>
</li>
<li v-for="(item, idx) in mybanner" v-if="idx === 0">
<a class="bannera" href="" :data-form="item.form" :data-actCode="item.actCode">
<img :src="item.banner" alt="">
</a>
</li>
</ul>
至此,基本實(shí)現(xiàn)了自動(dòng)播放輪播效果谎亩,下一版本想著改變思路來做了炒嘲。代碼還是放在這記錄一下宇姚,算是思路的軌跡....
????????????
未完待續(xù)...
參考資料:
Vue輪播圖的實(shí)現(xiàn)以及其與jQuery輪播圖的簡(jiǎn)單對(duì)比
JS bin代碼演示
mint-ui swiper