摘要:移動端滑動反彈什么是滑動就是類似于端的滾動事件,但是在移動端是沒有滾動事件的,所以就要用到事件結合去實現,效果如下準備工作什么是移動端的事件在移動端事件可以細分成三種,分別是和,并且事件必須要用去監聽。
移動端 Touch 滑動反彈
什么是Touch滑動?就是類似于PC端的滾動事件,但是在移動端是沒有滾動事件的,所以就要用到Touch事件結合js去實現,效果如下:1. 準備工作
什么是移動端的Touch事件?在移動端Touch事件可以細分成三種,分別是:touchstart、touchmove和touchend,并且touch事件必須要用addEventListener去監聽。
touchStart當手指觸碰到屏幕的時候觸發
touchmove當手指在屏幕上不斷移動的時候觸發
touchend當手指離開屏幕的時候觸發
Touch 事件觸發的 Event 對象:
// 手指觸碰到屏幕時觸發 element.addEventListener("touchstart", function (e) { // 打印的事件對象 console.log(e); })
changedTouches、targetTouches、touches都是偽數組,里面裝的是手指列表
三種返回對象的區別:
其實這三種返回的對象,都是表示用戶觸摸事件時的手指信息,之所以是一個偽數組,是因為有可能出現多指同時觸摸,但是在實際工作中一般不去考慮多指的情況。而它們唯一的區別就是在touchstart和touchmove事件的時候,changedTouches、targetTouches、touches都能獲取到手指的信息,但是在touchend事件的時候,targetTouches、touches對象是不能返回離開屏幕時的手指信息,只有changedTouches對象能返回。
有哪些手指信息?
我們可以看下上面的圖片,在changedTouche[0]中,有些值:
clientX:74 // 觸摸點相對于瀏覽器的 viewport 左邊緣的 x 坐標,不會包括左邊的滾動距離。 clientY:73 // 觸摸點相對于瀏覽器的 viewport 上邊緣的 Y 坐標,不會包括上邊的滾動距離。 screenX:2202 // 觸摸點相對于屏幕左邊緣的 x 坐標。 screenY:327 // 觸摸點相對于屏幕上邊緣的 Y 坐標。 pageX:65 // 觸摸點相對于 document 的左邊緣的 x 坐標,包括左邊的滾動距離 pageY:18 // 觸摸點相對于 document 的上邊緣的 Y 坐標,包括左邊的滾動距離2. 基本結構
此案例模擬的是移動端的一種滑動菜單效果。
HTML部分:
css部分:
在列表的父盒子上設定一個overflow: hidden屬性,使超出盒子部分的列表暫時隱藏掉,后面會通過js去實現滑動。
/* 樣式初始化 */ * { margin: 0; padding: 0; } html, body { width: 100%; } aside { height: 100%; width: 100%; } /* 列表的父盒子,限制寬高 */ /* 注意設置overflow: hidden;樣式后,超出這個盒子的ul將不會顯示 */ .draw { width: 60px; height: 500px; border: 2px solid #ccc; overflow: hidden; position: fixed; left: 10px; top: 50%; transform: translateY(-50%); } /* li 設置了浮動, 所以 ul 要清除浮動 */ ul:after { content: ""; display: block; visibility: hidden; height: 0; clear: both; } ul { zoom: 1; } li { list-style: none; float: left; width: 60px; height: 60px; line-height: 60px; text-align: center; }
效果圖:
3. 首次滑動手指觸摸到列表向下滑動的時候,列表應該跟著向下滑動,當手指離開屏幕的時候,列表應該停在滑動的位置。這里就會用到上面準備階段的知識點了,不明白的可以參考上面的概念。
實現原理:
1、touchstart的時候,獲取手指觸摸的落點A,通過這個點對象里面的clientY屬性,獲取距離頂部可視區的距離;
2、touchmove的時候,獲取手指的點B,同樣的獲取移動時距離頂部可視區的距離;
3、touchmove的時候,還要做另一件事情,就是獲取兩點的差值(B.clientY-A.clientY),將這個差值動態賦值給ul,ul只需要設置向Y軸方向偏移這個距離,就能實現列表隨手指滑動
先來張示意圖,怎么通過 js 讓列表滑動起來:
示例代碼:
var draw = document.querySelector("#draw"); var ul = draw.children[0]; // touchstart 時,記錄手指在 Y 軸上的落點距離可視頂部距離 var startY = 0 ul.addEventListener("touchstart", function (e) { startY = e.changedTouches[0].clientY; }) // touchmove 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchmove", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 設置 ul 在 Y 軸上的偏移 ul.style.transform = "translateY(" + dy + "px)"; })
效果圖:
4. 再次滑動上面的效果圖,細心的朋友可能已經發現了問題,在第一次的時候,得到了我們想要的效果,但是在第二次的時候,我們繼續向下移動了一段距離,但是ul并沒有接著第一次的位置繼續向下,而是瞬間跳了上去。
問題分析:
雖然第二次是繼續向下移動了一段距離,但是觸摸結束后,最終是將此時的差值,重新賦值給了ul的Y軸偏移,所以視覺上“跳了上去”。
解決方法:
每一次滑動結束之后,都應該記錄下此次滑動的距離,與之前的進行累加,待下一次滑動的時候,ul在Y軸的偏移值應該是之前的距離加上本次滑動的距離。
新增touchend事件,在該事件里同樣的可以獲取到本次滑動的距離,將它與上一次的距離相加,賦值給一個全局變量;
在touchmove事件里有點小改動,就是在給ul設置偏移值的時候,除了本次滑動的差值還要加上這個上一次的值;
示意圖:
示例代碼:
var draw = document.querySelector("#draw"); var ul = draw.children[0]; var startY = 0 // 剛觸碰到屏幕的時的手指信息 var centerY = 0 // 用來記錄每次觸摸時上一次的偏移距離 // touchstart 時,記錄手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchstart", function (e) { startY = e.changedTouches[0].clientY; }) // touchmove 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchmove", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 上次的滑動距離加上本次的滑動距離 var tempY = centerY + dy; // 設置 ul 在 Y 軸上的偏移 ul.style.transform = "translateY(" + tempY + "px)"; }) // touchend 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchend", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 記錄移動的距離 centerY = centerY + dy; })
效果圖:
5. 限制滑動區間到上面一步,我們已經可以實現列表的滑動了,但是也存在一個問題,就是向上或者向下的時候沒有限制,上下可以無限的滑動,甚至再用點力,就看不到列表了。為了美觀和實用,這樣肯定不行的,需要給它設定一個區間,設定向上或者向下最多只能留白多少。
限制向下滑動最大區間:
設定向下最大區間的值比較簡單,直接設定一個值,當上一次滑動的距離加上本次滑動的距離大于這個值的時候,就不讓它再繼續往下滑了,讓他直接等于這個設定的值。
示例代碼:
var maxDown = 50; // 設定一個最大向下滑動的距離 // touchmove 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchmove", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 上次的滑動距離加上本次的滑動距離 var tempY = centerY + dy; // 當上次滑動的距離加上本次滑動的距離 大于 設定的最大向下距離的時候 if (tempY > maxDown) { // 直接讓偏移的值 等于這個設定值 tempY = maxDown; } // 設置 ul 在 Y 軸上的偏移 ul.style.transform = "translateY(" + tempY + "px)"; })
限制向上滑動最大區間:
向上滑動時,當ul的底部距盒子底部的距離大于設定值的時候,不讓其繼續向上滑動,關鍵是這個值怎么去判斷?
求出向上滑動最大值:
注意:因為ul是向上滑動的,所以求得的距離前面要加上一個負號(-)
示例代碼:
// 設定一個最大向下滑動的距離 var maxDown = 50; // 求得一個最大向上滑動的距離 var maxUp = -(ul.offsetHeight - draw.offsetHeight + maxDown); // touchmove 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchmove", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 上次的滑動距離加上本次的滑動距離 var tempY = centerY + dy; // 當上次滑動的距離加上本次滑動的距離 大于 設定的最大向下距離的時候 if (tempY > maxDown) { tempY = maxDown; } // 當上次滑動的距離加上本次滑動的距離 小于 設定的最大向上距離的時候 else if (tempY < maxUp) { // 直接讓偏移的值 等于這個設定值 tempY = maxUp; } // 設置 ul 在 Y 軸上的偏移 ul.style.transform = "translateY(" + tempY + "px)"; })
效果圖:
認真觀察上圖,雖然成功的設置了最大滑動區間,但是你有沒有發現,一直往一個方向滑動的時候,雖然列表不會繼續往下滑動,但是接著往相反方向滑動的時候,感覺列表滑不動,需要滑一段距離后,列表才會跟著走,這是為什么呢?因為滑動的過程centerY是一直變的,列表雖然視覺上不動了,但是在touchend事件的時候,它的centerY值一直在累加。解決方法請往下看:
6. 設定反彈區間“滑動反彈”,這里的反彈是本篇文章的最后一步,上面說到的問題,就在這里解決。因為每一次觸發touchend事件的時候,centerY值就累加一次,所以需要在touchend事件里做判斷。我們設定一個反彈區間,就是當centerY的值大于或者小于某個值的時候,讓它觸發反彈。
設定向上反彈值:
向上的值比較簡單,設置成“0”。為什么是“0”呢?我們限定只要手指離開時,上一次的滑動距離加上本次的距離> 0的時候,就讓它觸發反彈,并且反彈回0點的位置,也就是兩次滑動的距離和= 0。
示例代碼:
// 向上反彈 var maxUpBounce = 0; // touchend 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchend", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 記錄移動的距離 centerY = centerY + dy; // 兩次滑動的距離 大于 設定的 向上 反彈值時 if (centerY > maxUpBounce) { // 讓兩次滑動的距離 等于 設置的值 centerY = maxUpBounce; // 添加過渡 ul.style.transition = "transform .5s"; ul.style.transform = "translateY(" + centerY + "px)"; } })
設定向下反彈值:
向下的值其實跟之前求滑動區間差不多,我們參考下圖,當列表向上滑動,滑動到列表底部的時候,只要此時再向上滑動,就讓它向下反彈。向下反彈值就是-(ul.offsetHeight - draw.offsetHeight),只要滑動的差值小于這個設定值,就讓它向下反彈,并且反彈回設定值的位置。
示例代碼:
// 向上反彈值 var maxUpBounce = 0; // 向下反彈值 var maxDownBounce = -(ul.offsetHeight - draw.offsetHeight); // touchend 時,記錄此時手指在 Y 軸上的落點距離可視頂部距離 ul.addEventListener("touchend", function (e) { // 獲取差值 var dy = e.changedTouches[0].clientY - startY; // 記錄移動的距離 centerY = centerY + dy; // 兩次滑動的距離 大于 設定的 向上 反彈值時 if (centerY > maxUpBounce) { // 讓兩次滑動的距離 等于 設置的值 centerY = maxUpBounce; // 添加過渡 ul.style.transition = "transform .5s"; ul.style.transform = "translateY(" + centerY + "px)"; } // 兩次滑動的距離 小于 設定的 向下 反彈值時 else if (centerY < maxDownBounce) { // 讓兩次滑動的距離 等于 設置的值 centerY = maxDownBounce; // 添加過渡 ul.style.transition = "transform .5s"; ul.style.transform = "translateY(" + centerY + "px)"; } })
注意: 在touchend事件的時候,給列表添加了transition屬性才會有反彈的效果,但是,下一次滑動的時候,touchmove事件的時候,這個屬性還存在,所以就會出現滑動的時候有頓挫感,所以在touchmove事件的時候,一進來就清一下過渡ul.style.transition = "none";。
完成后效果圖:
7. 完整代碼移動端 Touch 滑動反彈
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117241.html
摘要:移動端滑動反彈什么是滑動就是類似于端的滾動事件,但是在移動端是沒有滾動事件的,所以就要用到事件結合去實現,效果如下準備工作什么是移動端的事件在移動端事件可以細分成三種,分別是和,并且事件必須要用去監聽。 showImg(https://segmentfault.com/img/remote/1460000017852500?w=1920&h=1080); 移動端 Touch 滑動反彈 ...
摘要:輪播圖輪播圖其實就是通過手指的滑動,來左右切換輪播圖,下面我們通過一個案例,來實現下。結構結構上,還是用來存放輪播圖片,來存放輪播小圓點樣式初始化的一些標簽,都會有一些默認樣式,比如標簽默認是有一個邊距的,為了不影響美觀,我們需要清除掉。 showImg(https://segmentfault.com/img/remote/1460000017719408?w=1920&h=1080...
摘要:為了模擬原生應用的觸控效果,大量的應用使用了手指跟隨的滑動效果,也就是用手指滑動幻燈片的效果,什么是手指跟隨如圖網上滑動插件有不少,但好像沒一個好用的不是太多,就是不靈活這里用原生實現了該功能,不僅代碼量不多,邏輯也較簡單。 為了模擬原生應用的觸控效果,大量的H5應用使用了手指跟隨的滑動效果,也就是用手指滑動幻燈片的效果, 什么是手指跟隨,如圖;showImg(https://segm...
閱讀 3626·2023-04-25 23:32
閱讀 2042·2019-08-30 15:55
閱讀 2656·2019-08-30 15:52
閱讀 3114·2019-08-30 10:54
閱讀 843·2019-08-29 16:16
閱讀 651·2019-08-29 15:09
閱讀 3653·2019-08-26 14:05
閱讀 1636·2019-08-26 13:22