vue.js項(xiàng)目使用原生js實(shí)現(xiàn)移動(dòng)端的輪播圖
前言
今天我在vue.js項(xiàng)目實(shí)戰(zhàn)開(kāi)發(fā)過(guò)程中遇到了實(shí)現(xiàn)輪播圖效果的問(wèn)題,因?yàn)椴幌胍驗(yàn)橐粋€(gè)輪播圖而引用整個(gè)jquery,而且我還發(fā)現(xiàn)自己根本就不清楚移動(dòng)端的一些事件,所以我就進(jìn)行了一些資料查找,并最終解決了這個(gè)問(wèn)題,接下來(lái)跟大家分享一下我的解決問(wèn)題的過(guò)程.
一、了解原生js移動(dòng)端的事件
原生js移動(dòng)端的事件一共有四種:
事件 | 作用 |
---|---|
touchstart | 手指放到屏幕上觸發(fā) |
touchmove | 手指在屏幕上移動(dòng)觸發(fā)(高頻觸發(fā)) |
touchend | 手指離開(kāi)屏幕觸發(fā) |
touchcancel | 系統(tǒng)取消touch事件時(shí)觸發(fā) |
在每個(gè)事件被觸發(fā)后,會(huì)返回一個(gè)event參數(shù),event里面包含著三個(gè)觸摸列表,即:
event中的觸摸列表 | 內(nèi)容 |
---|---|
touches | 屏幕上所有的手指列表 |
targetTouches | 當(dāng)前這個(gè)DOM中的手指列表 |
changedTouches | 涉及當(dāng)前事件的手指列表(本實(shí)例中盡量用這個(gè)) |
觸摸列表中每個(gè)觸摸對(duì)象(即每個(gè)手指)都對(duì)應(yīng)著一些觸摸時(shí)生成的信息(只寫了部分)
觸摸信息 | 含義 |
---|---|
clientX / clientY | 觸摸點(diǎn)相對(duì)于瀏覽器的位置 |
pageX / pageY | 觸摸點(diǎn)相對(duì)于頁(yè)面的位置 |
screenX / screenY | 觸摸點(diǎn)相對(duì)于屏幕的位置 |
總結(jié):我們可以用觸摸事件傳入的參數(shù)event.changedTouches[0].pageX 獲得我們觸發(fā)( event )觸摸事件那個(gè)手指( changedTouches[0] )當(dāng)前位置相對(duì)于頁(yè)面的位置( pageX )
二、輪播圖實(shí)戰(zhàn)
我們做的輪播圖功能中只用到前三種觸發(fā)事件,我們來(lái)看一下具體的應(yīng)用。
因?yàn)関ue.js項(xiàng)目中都是以組件的形式來(lái)開(kāi)發(fā)的,所以我這里就以一個(gè)組件的形式來(lái)展示,有疑問(wèn)的可以留言詢問(wèn)。
第一部分:template模板
<template> <div class="ContinuPlay_box" @touchstart="TouchStart" @touchmove="TouchMove" @touchend="TouchEnd"> <div class="items_box"> <div v-for="(item, index) in banners" class="slide" :key="index"> <a :href="item.link" rel="external nofollow" > <img :src="item.image" alt=""> </a> </div> </div> <div class="points_box"> <div class="points"> <div class="each_point" v-for="(item, index) in banners.length" :key="index" :class="{current:index==CurrentImg}"></div> </div> </div> </div> </template>
第一部分解讀:
1.class="ContinuPlay_box"的div標(biāo)簽作為組件模板里的根標(biāo)簽包裹內(nèi)部標(biāo)簽(知識(shí)點(diǎn):組件內(nèi)如果多個(gè)標(biāo)簽處于同級(jí),必須用一個(gè)標(biāo)簽將他們包裹起來(lái)),也用于設(shè)置overflow:hidden樣式,用來(lái)隱藏未播放的輪播圖
2.class="items_box"的div標(biāo)簽作為內(nèi)部class=“slide” 的div標(biāo)簽的父標(biāo)簽,用來(lái)開(kāi)啟flex布局,該標(biāo)簽內(nèi)主要內(nèi)容就是輪播圖圖片
3.class=“slide” 的div標(biāo)簽用v-for指令對(duì)父組件傳進(jìn)來(lái)的數(shù)據(jù)banners進(jìn)行遍歷并輸出
4.class="points"的div標(biāo)簽作為內(nèi)部class="each_point"的div標(biāo)簽的父標(biāo)簽,用來(lái)開(kāi)啟flex布局,讓輪播圖的中下方的小圓點(diǎn)有序排列,該標(biāo)簽內(nèi)部主要內(nèi)容就是輪播圖中間下方的進(jìn)度條小圓點(diǎn)
第二部分:script標(biāo)簽內(nèi)代碼
<script> export default { name: "ContinuPlay", props:['banners'], //接受父級(jí)組件傳過(guò)來(lái)的banners數(shù)據(jù) data(){ return{ bannerwidth: 0, //輪播圖寬度 StartPoint: 0, //觸摸開(kāi)始的點(diǎn)的橫坐標(biāo) EndPoint: 0, //觸摸結(jié)束的點(diǎn)的橫坐標(biāo) MoveLength: 0, //StartPoint與EndPoint的差值 CurrentImg: 0, //當(dāng)前輪播圖的索引 isPlaying: true, //判斷是否處于自動(dòng)輪播 playTimer: null //輪播定時(shí)器 } }, methods:{ TouchStart(event){ //停止輪播 clearInterval(this.playTimer) //獲取觸摸的開(kāi)始點(diǎn) this.StartPoint = event.changedTouches[0].pageX }, TouchMove(event){ //獲取觸摸的結(jié)束點(diǎn) this.EndPoint = event.changedTouches[0].pageX this.slidings() }, TouchEnd(){ this.Jump() //開(kāi)始輪播 this.startPlay() }, //Jump()方法用于處理滑動(dòng)到一定程度后松手自動(dòng)跳轉(zhuǎn)到下一頁(yè)或上一頁(yè) Jump(){ const currentimg = document.getElementsByClassName('slide') //滑動(dòng)超過(guò)輪播圖寬度的百分之40,則跳轉(zhuǎn)下一張,否則不跳轉(zhuǎn) if(this.MoveLength > 0 && this.CurrentImg !== this.banners.length-1){ if(this.MoveLength > this.bannerwidth * 0.4){ this.CurrentImg ++ currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px' } else{ currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px' } } else if(this.MoveLength < 0 && this.CurrentImg !== 0){ if(-this.MoveLength > this.bannerwidth * 0.4){ this.CurrentImg -- currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px' } else{ currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px' } } }, //slidings()方法用于處理在滑動(dòng)過(guò)程中,輪播圖跟著手指滑動(dòng)的距離移動(dòng) slidings(){ //判斷是點(diǎn)擊還是滑動(dòng) if(this.StartPoint === this.EndPoint){return} this.MoveLength = this.StartPoint - this.EndPoint //操作DOM,獲取輪播圖對(duì)象標(biāo)簽 const currentimg = document.getElementsByClassName('slide') //獲取輪播圖的寬度 this.bannerwidth = currentimg[0].offsetWidth //判斷是否超出滑動(dòng)范圍,即第一頁(yè)無(wú)法再往前一頁(yè)滑動(dòng),最后一頁(yè)無(wú)法再往后一頁(yè)滑動(dòng) if(this.MoveLength > 0 && this.CurrentImg !== this.banners.length-1){ currentimg[0].style.marginLeft = -this.MoveLength - this.CurrentImg * this.bannerwidth + 'px' } else if(this.MoveLength < 0 && this.CurrentImg !== 0){ currentimg[0].style.marginLeft = -this.MoveLength - this.CurrentImg * this.bannerwidth + 'px' } }, //開(kāi)啟輪播 startPlay() { clearInterval(this.playTimer) this.playTimer = setInterval(() => { if(this.CurrentImg === 3) { this.CurrentImg = -1 } this.CurrentImg ++ const currentimg = document.getElementsByClassName('slide') this.bannerwidth = currentimg[0].offsetWidth currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px' currentimg[0].style.transition = 'all 1s ease' }, 3000) } }, mounted() { //頁(yè)面掛在完畢自動(dòng)開(kāi)啟輪播 this.startPlay() } } </script>
第二部分解讀:
1.在組件data屬性中,初始化了幾個(gè)變量:StartPoint(觸摸開(kāi)始點(diǎn)橫坐標(biāo))、EndPoint(觸摸結(jié)束時(shí)橫坐標(biāo))、MoveLength(移動(dòng)的長(zhǎng)度(有正負(fù)))、CurrentImg(當(dāng)前輪播圖索引)
2.在頁(yè)面掛在完成后, 觸發(fā)methods中的startPlay方法,開(kāi)啟輪播功能
3.在觸摸事件中主要運(yùn)用 StartPoint - EndPoint 的值使得圖片跟著手指的滑動(dòng)方向同步移動(dòng), 并且在觸摸開(kāi)始時(shí),關(guān)閉自動(dòng)輪播定時(shí)器,在觸摸結(jié)束后,自動(dòng)開(kāi)啟輪播定時(shí)器
4.在松手后,通過(guò)Jump() 方法進(jìn)行跳轉(zhuǎn)上下頁(yè)圖片
第三部分:css樣式部分
<style scoped> .ContinuPlay_box{ overflow: hidden; position: relative; } .ContinuPlay_box .items_box{ display: flex; } .ContinuPlay_box .slide{ flex-shrink: 0; width: 100%; } .ContinuPlay_box .slide img, .ContinuPlay_box .slide a{ width: 100%; height: 100%; } .points_box{ display: flex; justify-content: center; } .points{ display: flex; width: 33%; height: 10px; position: absolute; bottom: 8px; justify-content: space-evenly; } .points .each_point{ width: 8px; height: 8px; border-radius: 8px; background: #fff; opacity: 0.7; } .points .current{ background: #ff0031; } </style>
css樣式就不做多解釋了,因?yàn)檫@比較抽象,你們可以根據(jù)我的代碼進(jìn)行調(diào)試優(yōu)化,我的應(yīng)該也不是最好的
三、效果圖
此gif圖展示的是我現(xiàn)在已經(jīng)開(kāi)發(fā)的部分項(xiàng)目效果圖,其中包括本文講的輪播圖功能
結(jié)束語(yǔ)
2020.05.01 這是我在vue.js實(shí)戰(zhàn)項(xiàng)目開(kāi)發(fā)第二天中遇到的問(wèn)題,希望我遇到的問(wèn)題能對(duì)大家有所幫助, 如果大家感興趣,可以關(guān)注一波,每天跟大家分享一些問(wèn)題和解決辦法,大家也可以跟我分享一下你們的經(jīng)驗(yàn)。
更多關(guān)于原生js移動(dòng)端輪播圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Vue CLI3 多頁(yè)應(yīng)用實(shí)踐和源碼設(shè)計(jì)
這篇文章主要介紹了詳解Vue CLI3 多頁(yè)應(yīng)用實(shí)踐和源碼設(shè)計(jì),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08js節(jié)流防抖應(yīng)用場(chǎng)景,以及在vue中節(jié)流防抖的具體實(shí)現(xiàn)操作
這篇文章主要介紹了js節(jié)流防抖應(yīng)用場(chǎng)景,以及在vue中節(jié)流防抖的具體實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09vue中計(jì)算屬性computed理解說(shuō)明包括vue偵聽(tīng)器,緩存與computed的區(qū)別
這篇文章主要介紹了對(duì)vue中計(jì)算屬性computed理解說(shuō)明包括vue偵聽(tīng)器,緩存與computed的區(qū)別,需要的朋友可以參考下2022-05-05手把手教你寫一個(gè)vue全局注冊(cè)的Toast的實(shí)現(xiàn)
本文主要介紹了手把手教你寫一個(gè)vue全局注冊(cè)的Toast的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Vue3?+?elementplus實(shí)現(xiàn)表單驗(yàn)證+上傳圖片+?防止表單重復(fù)提交功能
這篇文章主要介紹了Vue3?+?elementplus?表單驗(yàn)證+上傳圖片+?防止表單重復(fù)提交,本文給大家展示效果圖和完整代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10Vue Elenent實(shí)現(xiàn)表格相同數(shù)據(jù)列合并
這篇文章主要為大家詳細(xì)介紹了Vue Elenent實(shí)現(xiàn)表格相同數(shù)據(jù)列合并,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11Vue 使用formData方式向后臺(tái)發(fā)送數(shù)據(jù)的實(shí)現(xiàn)
這篇文章主要介紹了Vue 使用formData方式向后臺(tái)發(fā)送數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04