摘要:其次父組件中負(fù)責(zé)通用的功能,以及輪播的整體架構(gòu),其結(jié)構(gòu)如下。下面的是一種移動(dòng)端的適配方案。接下來實(shí)現(xiàn)函數(shù)運(yùn)用動(dòng)畫切換到指定下標(biāo)的子項(xiàng)到此為止,咱們就已經(jīng)完成了一個(gè)初步的滑動(dòng)切換輪播圖的功能了。
前言
昨天寫了一篇側(cè)邊菜單組件的文章,閱讀人數(shù)挺多的,內(nèi)心很欣喜(偷著樂,第一篇文章有這么多人看)!乘著這股勁,今天在繼續(xù)寫一篇我們平時(shí)工作中更常用的滑動(dòng)輪播組件的文章。
效果展示老規(guī)矩,咱們先看做成后的效果,然后咱們再一步步的開始制作:
在實(shí)際的工作中,咱們輪播中的內(nèi)容形式可能有很多種:圖片、文本、視頻、其他DOM結(jié)構(gòu)等。所以咱們的輪播組件必須能滿足這幾種應(yīng)用情況。那么我們可以把組件分兩部分:
可以高度定制的子組件,負(fù)責(zé)渲染輪播中的每一個(gè)子項(xiàng)
負(fù)責(zé)輪播的父組件,用來處理通用的滑動(dòng)事件、自動(dòng)輪播、指示器等功能
我們現(xiàn)在這定義子組件的名稱為swiper-item;父組件名稱為swiper
DOM組成首先咱們的子組件中負(fù)責(zé)渲染自定義的內(nèi)容,則子組件中需要一個(gè)插槽slot。
swiper-item:
其次父組件中負(fù)責(zé)通用的功能,以及輪播的整體架構(gòu),其DOM結(jié)構(gòu)如下。
swiper:
默認(rèn)插槽在使用的時(shí)候渲染咱們輪播的子項(xiàng),通常為swiper-item;indicator插槽用來自定義指示器的樣式,因?yàn)樵趯?shí)際使用過程中指示器樣式很可能是需要定制的。
css樣式移動(dòng)端的視圖大小有限,子項(xiàng)的大小一般是父組件的全部可視視圖。
swiper-item:
下面的vw是一種移動(dòng)端的適配方案(https://www.w3cplus.com/css/t...)。其他的適配方案還有淘寶的flexible,這個(gè)css大家根據(jù)自己的適配方案更改下,這里不做過多描述,大家感興趣的自行百度。
swiper:
老規(guī)矩,寫JS代碼前咱們先理清交互邏輯:
頁面渲染開始,首先把所有子組件掛載到DOM上,當(dāng)所有子節(jié)點(diǎn)掛載好了后初始化父組件
同理,當(dāng)輪播組件銷毀的時(shí)候先銷毀子組件,再銷毀父組件
初始化的時(shí)候需要:
獲取父組件容器DOM節(jié)點(diǎn)、以及父組件節(jié)點(diǎn)的寬度
獲取到所有子組件節(jié)點(diǎn)
給所有子節(jié)點(diǎn)依次設(shè)置好初始坐標(biāo)
給父節(jié)點(diǎn)綁定touch事件
初始化完成后,當(dāng)手指觸摸到屏幕瞬間,記錄當(dāng)前手指起始的坐標(biāo)
當(dāng)手指移動(dòng)的過程中,阻止頁面中的默認(rèn)事件,根據(jù)當(dāng)前坐標(biāo)以及起始坐標(biāo)計(jì)算手指X、Y軸移動(dòng)的距離
如果X軸移動(dòng)比Y軸多則判斷手指在橫向移動(dòng),否則為豎向移動(dòng)
如果橫向移動(dòng)則移動(dòng)子項(xiàng)中的位置,修改所有子項(xiàng)的坐標(biāo)
手指離開屏幕的時(shí)候判斷手指移動(dòng)總距離,如果大于一個(gè)臨界值則輪播切換到下一屏或者上一屏(根據(jù)滑動(dòng)方向判定),否則重置會(huì)原始狀態(tài)
swiper-item:
export default { mounted () { this.$nextTick(() => { this.$parent.init() }) }, beforeDestroy () { this.$nextTick(() => { this.$parent.destroy() }) } }
swiper:
初始化完成后,咱們接下來編寫咱們的moveStart、moving、moveEnd三個(gè)touch事件,在methods中完善這三個(gè)函數(shù),并添加一個(gè)臨界值sensitivity以及一個(gè)阻力系數(shù),阻力系數(shù)有啥用,注意看下面代碼的注釋:
data () { return { sensitivity: 60, resistance: 0.3 } }, methods: { moveStart (e) { this.start.x = e.changedTouches[0].pageX this.start.y = e.changedTouches[0].pageY this.setTransition("none") }, moving (e) { e.preventDefault() e.stopPropagation() let distanceX = e.changedTouches[0].pageX - this.start.x let distanceY = e.changedTouches[0].pageY - this.start.y if (Math.abs(distanceX) > Math.abs(distanceY)) { this.isMoving = true this.move.x = this.start.x + distanceX this.move.y = this.start.y + distanceY // 當(dāng)活動(dòng)子項(xiàng)為第一項(xiàng)且手指向右滑動(dòng)或者活動(dòng)項(xiàng)為最后一項(xiàng)切向左滑動(dòng)的時(shí)候,添加阻力,形成一個(gè)拉彈簧的效果 if ((this.active === 0 && distanceX > 0) || (this.active === (this.items.length - 1) && distanceX < 0)) { distanceX = distanceX * this.resistance } this.setTransform(distanceX) } }, moveEnd (e) { if (this.isMoving) { e.preventDefault() e.stopPropagation() let distance = this.move.x - this.start.x if (Math.abs(distance) > this.sensitivity) { if (distance < 0) { this.next() } else { this.prev() } } else { this.back() } this.reset() this.isMoving = false } }, // 切換下一屏 next () {}, // 切換下一屏 prev () {}, // 如果滑動(dòng)達(dá)不到閾值,所有元素重置回之前狀態(tài) back () {}, // 重置動(dòng)畫中用到的一些變量 reset () {}, destroy () { this.setTransition("none") } }
接下來咱們完善下next、prev、back、reset函數(shù):
next () { let index = this.active + 1 // 運(yùn)用動(dòng)畫切換到指定下標(biāo)的子項(xiàng) this.go(index) }, prev () { let index = this.active - 1 // 運(yùn)用動(dòng)畫切換到指定下標(biāo)的子項(xiàng) this.go(index) }, reset () { this.start.x = 0 this.start.y = 0 this.move.x = 0 this.move.y = 0 }, back () { this.setTransition() this.setTransform() }, go (index) {}
go函數(shù)用來做輪播切換的效果。我們在寫代碼的過程中,可以先定義一個(gè)函數(shù)來做某個(gè)事情,然后再后面用代碼來實(shí)現(xiàn)邏輯,這樣的咱們寫代碼過程中的思路就會(huì)很清晰。接下來實(shí)現(xiàn)go函數(shù):
// 運(yùn)用動(dòng)畫切換到指定下標(biāo)的子項(xiàng) go (index) { this.active = index if (this.active < 0) { this.active = 0 } else if (this.active > this.items.length - 1) { this.active = this.items.length - 1 } this.$emit("change", this.active) this.setTransition() this.setTransform() }
到此為止,咱們就已經(jīng)完成了一個(gè)初步的滑動(dòng)切換輪播圖的功能了。但是很多時(shí)候,我們的輪播是需要自動(dòng)播放的,那么如何在現(xiàn)在的基礎(chǔ)上增加自動(dòng)輪播呢?請大家自己思考下,哈哈。下面我們把當(dāng)前代碼整合下:
寫在最后
今天寫這篇文章的時(shí)候發(fā)現(xiàn)有兩個(gè)兄弟給我微信轉(zhuǎn)了錢,很謝謝這兩個(gè)兄弟,感謝你們的支持。其實(shí)說實(shí)話,我花心思寫這個(gè)主要目的不是為了錢,而是興趣,否則我用這個(gè)時(shí)間用來做點(diǎn)私活什么的收入比這個(gè)多多了。只是看到大家的支持,內(nèi)心很有成就感,盡管很多時(shí)候只有1分錢,所以也希望大家有錢的捧個(gè)錢場,沒錢的捧個(gè)人場,哈哈。(未完待續(xù)...)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93270.html
摘要:最后提醒下,代碼中使用而非的原因是為了啟動(dòng)移動(dòng)端手機(jī)的動(dòng)畫加速,提升動(dòng)畫流暢度。 前言 最近面試發(fā)現(xiàn)很多前端程序員都從來沒有寫過插件的經(jīng)驗(yàn),基本上都是網(wǎng)上百度。所以打算寫一系列文章,手把手的教一些沒有寫過組件的兄弟們?nèi)绾稳懖寮?。本系列文章都基于VUE,核心內(nèi)容都一樣,會(huì)了之后大家可以快速的改寫成react、angular或者是小程序等組件。這篇文章是第一篇,寫的是一個(gè)類似QQ的側(cè)邊菜...
摘要:前言在我們移動(dòng)端還有一個(gè)很常用的組件,那就是滑動(dòng)加載更多組件。平常我們看到的很多插件實(shí)現(xiàn)相當(dāng)復(fù)雜就覺得這個(gè)組件很難,其實(shí)不是的這個(gè)組件其實(shí)可以很簡單的就實(shí)現(xiàn)出來,而且體驗(yàn)也能非常的棒當(dāng)然我們沒有實(shí)現(xiàn)下拉刷新功能下面我們就一起來實(shí)現(xiàn)這個(gè)組件。 前言 在我們移動(dòng)端還有一個(gè)很常用的組件,那就是滑動(dòng)加載更多組件。平常我們看到的很多插件實(shí)現(xiàn)相當(dāng)復(fù)雜就覺得這個(gè)組件很難,其實(shí)不是的?。∵@個(gè)組件其實(shí)可...
閱讀 1991·2021-11-22 14:45
閱讀 2610·2021-10-12 10:11
閱讀 776·2021-09-22 10:02
閱讀 1232·2019-08-30 15:55
閱讀 1147·2019-08-30 15:54
閱讀 3258·2019-08-30 15:54
閱讀 1196·2019-08-29 17:16
閱讀 3092·2019-08-28 17:55