移動(dòng)端左右滑動(dòng)切換頁(yè)面效果完整代碼(純JavaScript)
一.介紹左右滑動(dòng)的重要性
移動(dòng)端左右滑動(dòng)效果是一種常見(jiàn)的用戶(hù)界面交互方式,它能夠提供流暢的用戶(hù)體驗(yàn)并增強(qiáng)應(yīng)用的直觀性。以下是一些實(shí)現(xiàn)移動(dòng)端左右滑動(dòng)效果的場(chǎng)景和方法:
頁(yè)面切換:在移動(dòng)端應(yīng)用中,左右滑動(dòng)可以用來(lái)在不同的頁(yè)面或視圖之間切換。這種效果可以用于圖像畫(huà)廊、故事講述或?qū)Ш讲藛蔚葓?chǎng)景。
列表滑動(dòng):在長(zhǎng)列表中,用戶(hù)可以通過(guò)左右滑動(dòng)來(lái)瀏覽不同的列表項(xiàng)。這種滑動(dòng)效果可以提高用戶(hù)在瀏覽大量數(shù)據(jù)時(shí)的效率。
卡片式布局:在卡片式布局中,左右滑動(dòng)可以幫助用戶(hù)在不同的卡片之間切換,每個(gè)卡片代表一個(gè)獨(dú)立的信息塊或功能模塊。
彈出菜單:移動(dòng)端的彈出菜單或側(cè)邊欄可以通過(guò)左右滑動(dòng)來(lái)顯示或隱藏,為用戶(hù)提供更多的操作選項(xiàng)或信息。
過(guò)渡動(dòng)畫(huà):在Vue中,可以使用
transition
組件來(lái)實(shí)現(xiàn)左右滑動(dòng)的過(guò)渡動(dòng)畫(huà)。例如,可以通過(guò)監(jiān)聽(tīng)觸摸事件來(lái)捕捉用戶(hù)的滑動(dòng)動(dòng)作,并使用CSS過(guò)渡動(dòng)畫(huà)來(lái)實(shí)現(xiàn)平滑的頁(yè)面切換效果。滑動(dòng)庫(kù):如果需要快速實(shí)現(xiàn)滑動(dòng)效果,并且不需要過(guò)多的定制化,可以考慮使用第三方滑動(dòng)庫(kù),如Swiper、Hammer.js等。這些庫(kù)提供了豐富的API和更穩(wěn)定的體驗(yàn)。
自定義滑動(dòng)動(dòng)畫(huà):開(kāi)發(fā)者可以根據(jù)具體需求,使用CSS和JavaScript來(lái)實(shí)現(xiàn)自定義的滑動(dòng)動(dòng)畫(huà)效果。這包括定義動(dòng)畫(huà)樣式、監(jiān)聽(tīng)觸摸事件以及處理滑動(dòng)邏輯。
性能優(yōu)化:在實(shí)際項(xiàng)目中,還需要考慮性能優(yōu)化,如使用
keep-alive
來(lái)緩存頁(yè)面,減少頁(yè)面的重復(fù)渲染,以及使用防抖或節(jié)流技術(shù)來(lái)避免頻繁觸發(fā)事件。
通過(guò)這些方法,開(kāi)發(fā)者可以在移動(dòng)端應(yīng)用中實(shí)現(xiàn)左右滑動(dòng)效果,提升用戶(hù)的交互體驗(yàn)。
二、實(shí)現(xiàn)的思路
第一步:事件監(jiān)聽(tīng)
在移動(dòng)端實(shí)現(xiàn)滑動(dòng)效果,需要監(jiān)聽(tīng)三個(gè)關(guān)鍵的觸摸事件:
touchStart
:當(dāng)用戶(hù)開(kāi)始觸摸屏幕時(shí)觸發(fā)。touchMove
:當(dāng)用戶(hù)在屏幕上移動(dòng)手指時(shí)觸發(fā)。touchEnd
:當(dāng)用戶(hù)抬起手指,結(jié)束觸摸操作時(shí)觸發(fā)。
第二步:事件處理邏輯
接下來(lái),我們需要明確在每個(gè)事件觸發(fā)時(shí)應(yīng)該執(zhí)行的操作:
touchStart
事件:- 記錄觸摸開(kāi)始時(shí)的坐標(biāo)(
startX
)。 - 初始化滑動(dòng)距離(
distanceX
)為0。 - 重置滑動(dòng)容器的初始位置。
- 設(shè)置一個(gè)標(biāo)志(
isMove
)來(lái)跟蹤是否開(kāi)始滑動(dòng)。 - 代碼:
//按下 function handleTouchStart(e) { startX = e.touches[0].clientX; console.log(startX); //當(dāng)前按下的位置 }
- 記錄觸摸開(kāi)始時(shí)的坐標(biāo)(
touchMove
事件:- 獲取當(dāng)前觸摸點(diǎn)的坐標(biāo)(
currentX
)。 - 計(jì)算滑動(dòng)距離(
distanceX
)為當(dāng)前坐標(biāo)與起始坐標(biāo)的差值。 - 根據(jù)滑動(dòng)距離更新滑動(dòng)容器的位置。
- 判斷滑動(dòng)方向,如果超出邊界則限制滑動(dòng)范圍。
- 如果滑動(dòng)距離超過(guò)一定閾值,可以設(shè)置一個(gè)標(biāo)志來(lái)觸發(fā)頁(yè)面切換。
- 代碼:
//按下移動(dòng) function handleTouchMove(e) { const moveX = e.touches[0].clientX; // console.log(moveX); const movedDistance = Math.abs(moveX - startX); // 計(jì)算移動(dòng)的距離 console.log(movedDistance); // 如果移動(dòng)的距離小于80,不進(jìn)行更新位置的操作 if (movedDistance < 80) { return; } //如果 moveX 大于 startX 就是往右滑動(dòng) 并且頁(yè)數(shù)為0 就不行 ,或者 moveX 小于 startX 并且頁(yè)數(shù)是最后一頁(yè)頁(yè)不行 if ((moveX > startX && pageIndex === 0) || (moveX < startX && pageIndex === oSliderItems.length - 1)) { return } distanceX = moveX - startX; setTranslateX(-pageWith * pageIndex + distanceX) isMove = true; }
- 獲取當(dāng)前觸摸點(diǎn)的坐標(biāo)(
touchEnd
事件:- 判斷滑動(dòng)距離是否超過(guò)頁(yè)面切換的閾值。
- 如果超過(guò)閾值,執(zhí)行頁(yè)面切換邏輯。
- 如果未超過(guò)閾值,執(zhí)行回彈邏輯,將滑動(dòng)容器恢復(fù)到初始位置。
- 重置滑動(dòng)相關(guān)的變量,為下一次滑動(dòng)做準(zhǔn)備。
//松開(kāi) function handleTouchEnd() { if (isMove) { if (Math.abs(distanceX) >= pageWith / 3) { if (distanceX > 0) { pageIndex--; } if (distanceX < 0) { pageIndex++; } } setTranslateX(- pageIndex * pageWith) } startX = 0; distanceX = 0; isMove = false } function setTranslateX(tranX) { oScrollWrapper.style.transition = 'all .1s' oScrollWrapper.style.transform = `translate(${tranX}px)` }
注意:在touchMove 事件,中需要判斷一下,往右或者往左滑動(dòng)的距離是否大于50-80,這樣可以避免如果頁(yè)面是一個(gè)很長(zhǎng)的page,往下滾動(dòng)就會(huì)左右抖動(dòng),影響用戶(hù)體驗(yàn)。
-----全部代碼-以及效果展示 (JavaScript)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 37.5 + 'px' </script> <style> body { margin: 0; } html, body, #app { height: 100%; } div { display: flex; width: 100%; flex-direction: column; } .slider-page { position: relative; height: 100%; overflow: hidden; } .scroll-wrapper { position: absolute; width: 400vw; height: 100%; flex-direction: row; } .slider-item { width: 100vw; height: 100%; flex: 1; } .slider-item:nth-child(1) { background-color: rgb(247, 150, 150); } .slider-item:nth-child(2) { background-color: rgb(123, 255, 0); } .slider-item:nth-child(3) { background-color: rgb(0, 255, 238); } .slider-item:nth-child(4) { background-color: rgb(255, 0, 195); } .slider-item .inner { height: 100%; justify-content: center; align-items: center; font-size: 50px; } </style> </head> <body> <div id="app"> <div class="slider-page"> <div class="scroll-wrapper"> <div class="slider-item"> <div class="inner">Page1</div> </div> <div class="slider-item"> <div class="inner">Page2</div> </div> <div class="slider-item"> <div class="inner">Page3</div> </div> <div class="slider-item"> <div class="inner">Page4</div> </div> </div> </div> </div> <script> //oSlidePage 最大的頁(yè)面盒子 //oScrollWrapper內(nèi)部的盒子總寬 // oSliderItems 每個(gè)小盒子 // pageWith 頁(yè)面寬度 const oSlidePage = document.querySelector('.slider-page'), oScrollWrapper = oSlidePage.querySelector('.scroll-wrapper'), oSliderItems = oScrollWrapper.querySelectorAll('.slider-item'), pageWith = oSlidePage.offsetWidth; console.log('當(dāng)前視口的寬度', pageWith); // 移動(dòng)端事件 touchstart touchmove touchend let startX = 0, pageIndex = 0, distanceX = 0 isMove = false; //初始化 const init = () => { bindEvent() } function bindEvent() { oScrollWrapper.addEventListener('touchstart', handleTouchStart, false) oScrollWrapper.addEventListener('touchmove', handleTouchMove, false) oScrollWrapper.addEventListener('touchend', handleTouchEnd, false) } //按下 function handleTouchStart(e) { startX = e.touches[0].clientX; console.log(startX); } //按下移動(dòng) function handleTouchMove(e) { const moveX = e.touches[0].clientX; // console.log(moveX); const movedDistance = Math.abs(moveX - startX); // 計(jì)算移動(dòng)的距離 console.log(movedDistance); // 如果移動(dòng)的距離小于80,不進(jìn)行更新位置的操作 if (movedDistance < 80) { return; } //如果 moveX 大于 startX 就是往右滑動(dòng) 并且頁(yè)數(shù)為0 就不行 ,或者 moveX 小于 startX 并且頁(yè)數(shù)是最后一頁(yè)頁(yè)不行 if ((moveX > startX && pageIndex === 0) || (moveX < startX && pageIndex === oSliderItems.length - 1)) { return } distanceX = moveX - startX; setTranslateX(-pageWith * pageIndex + distanceX) isMove = true; } //松開(kāi) function handleTouchEnd() { if (isMove) { if (Math.abs(distanceX) >= pageWith / 3) { if (distanceX > 0) { pageIndex--; } if (distanceX < 0) { pageIndex++; } } setTranslateX(- pageIndex * pageWith) } startX = 0; distanceX = 0; isMove = false } function setTranslateX(tranX) { oScrollWrapper.style.transition = 'all .1s' oScrollWrapper.style.transform = `translate(${tranX}px)` } init() </script> </body> </html>
擴(kuò)展:實(shí)現(xiàn)滑動(dòng)效果并結(jié)合tab切換卡,實(shí)現(xiàn)思路如下:
1. 設(shè)計(jì)布局
首先,設(shè)計(jì)你的tab切換卡的布局。這通常包括一個(gè)頂部的tab欄和下方的內(nèi)容區(qū)域。每個(gè)tab對(duì)應(yīng)內(nèi)容區(qū)域中的一個(gè)頁(yè)面。
2. 使用變量控制高亮
使用一個(gè)變量(如pageIndex
)來(lái)跟蹤當(dāng)前激活的tab。這個(gè)變量將用于控制tab欄中哪個(gè)tab是高亮顯示的。
3. 實(shí)現(xiàn)滑動(dòng)邏輯
在滑動(dòng)邏輯中,除了更新滑動(dòng)容器的位置外,還需要根據(jù)滑動(dòng)的距離來(lái)更新pageIndex
。當(dāng)用戶(hù)滑動(dòng)到新頁(yè)面時(shí),相應(yīng)的tab應(yīng)該被高亮。
4. 監(jiān)聽(tīng)滑動(dòng)事件
在touchMove
和touchEnd
事件中,根據(jù)滑動(dòng)的距離來(lái)更新pageIndex
,并相應(yīng)地更新tab欄的高亮狀態(tài)。
總結(jié)
到此這篇關(guān)于移動(dòng)端左右滑動(dòng)切換頁(yè)面效果的文章就介紹到這了,更多相關(guān)js移動(dòng)端左右滑動(dòng)切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue實(shí)現(xiàn)移動(dòng)端左右滑動(dòng)效果的方法
- vue移動(dòng)端實(shí)現(xiàn)手機(jī)左右滑動(dòng)入場(chǎng)動(dòng)畫(huà)
- Swiper.js實(shí)現(xiàn)移動(dòng)端元素左右滑動(dòng)
- 移動(dòng)端手指操控左右滑動(dòng)的菜單
- vue移動(dòng)端的左右滑動(dòng)事件詳解
- jquery實(shí)現(xiàn)移動(dòng)端按鈕組左右滑動(dòng)
- vue中transition動(dòng)畫(huà)使用(移動(dòng)端頁(yè)面切換左右滑動(dòng)效果)
相關(guān)文章
發(fā)兩個(gè)小東西,ASP/PHP 學(xué)習(xí)工具。 用JavaScript寫(xiě)的
發(fā)兩個(gè)小東西,ASP/PHP 學(xué)習(xí)工具。 用JavaScript寫(xiě)的...2007-04-04js實(shí)現(xiàn)按鈕顏色漸變動(dòng)畫(huà)效果
這篇文章主要介紹了js實(shí)現(xiàn)按鈕顏色漸變動(dòng)畫(huà)效果的方法,涉及javascript鼠標(biāo)事件及頁(yè)面表單元素樣式的動(dòng)態(tài)操作技巧,需要的朋友可以參考下2015-08-08Web3.js查詢(xún)以太幣和代幣余額及轉(zhuǎn)賬
這篇文章主要介紹了Web3.js查詢(xún)以太幣和代幣余額以及轉(zhuǎn)賬,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09JavaScript原始數(shù)據(jù)類(lèi)型Symbol的用法詳解
Symbol是ES6中引入的一種新的基本數(shù)據(jù)類(lèi)型,用于表示一個(gè)獨(dú)一無(wú)二的值。它是JavaScript中的第七種數(shù)據(jù)類(lèi)型。本文將詳細(xì)講講Symbol的使用,需要的可以參考一下2022-11-11layui select 禁止點(diǎn)擊的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layui select 禁止點(diǎn)擊的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09js+html+css實(shí)現(xiàn)手動(dòng)輪播和自動(dòng)輪播
這篇文章主要為大家詳細(xì)介紹了js+html+css實(shí)現(xiàn)手動(dòng)輪播和自動(dòng)輪播效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12