詳解滑動(dòng)穿透(鎖body)終極探索
場景
當(dāng)頁面出現(xiàn)浮層的時(shí)候,滑動(dòng)浮層的內(nèi)容,正常情況下預(yù)期應(yīng)該是浮層下邊的內(nèi)容不會(huì)滾動(dòng);然而事實(shí)并非如此。
如圖所示,浮層下邊的內(nèi)容并沒有如想象中不受影響。
解決
先去github上搜索一番,發(fā)現(xiàn)有解決此問題的開源包,簡單粗暴直接挑選了其中star的最高的(body-scroll-lock)操作一番!
使用后發(fā)現(xiàn)有一些問題:
- 安卓端全掛
- ios端偶爾會(huì)有鎖不住的情況
查源碼發(fā)現(xiàn)該包在iOS端使用禁止touchmove的方式單獨(dú)處理,但是在其他端只是給body加overflow: hidden簡單處理。
于是決定寫一個(gè)針對(duì)多端通用的包來處理類似的問題。
探索一:overflow: hidden
看到下邊的滾動(dòng)肯定立刻就想到了是整個(gè)viewport的滾動(dòng),那么如果給body設(shè)置overflow: hidden,此時(shí)body的內(nèi)容就只有一屏了,肯定不會(huì)滾動(dòng)了;
body { overflow: hidden; }
此方案在pc端完美解決了我們的問題,然而事情并沒有那么簡單;
再試試移動(dòng)端:
移動(dòng)端中并沒有出現(xiàn)期待的效果。。。
既然pc端已經(jīng)有了完美的方案,下邊我們繼續(xù)探索移動(dòng)端的解決方案。
探索二:body定位
上邊想到給body設(shè)置overflow: hidden在移動(dòng)端并不能解決我們的問題,是否在于body的height沒有設(shè)置
- 將html、body的高度都設(shè)置為100%;
- 給body設(shè)置絕對(duì)定位(fixed);
同時(shí)使用這兩個(gè)操作似乎完美滿足了我們的需求;
但是如圖所示,每次都會(huì)將頁面拉到最頂上的位置,這樣看起來又不完美了;
既然使用了定位,那么給一個(gè)top值不就定位到我們想要的位置了(聰明如我)。
tips: body 設(shè)置 relative 定位會(huì)頁面自身拉上去,下邊留白
多次實(shí)驗(yàn)發(fā)現(xiàn)這個(gè)方案在android端中完美達(dá)到了我們想要的結(jié)果,但是在ios端并不理想;每次定位的時(shí)候會(huì)有閃動(dòng)的問題;好事多磨,接著探索ios端的方案。
探索三:禁止touchmove
如果禁止掉頁面的touchmove是否可行呢?話不多說就是干!
當(dāng)彈出浮層的時(shí)候禁掉頁面元素的touchmove
document.addEventListener('touchmove', function (event) { event.preventDefault() })
測試發(fā)現(xiàn)沒有達(dá)到想象中的效果,感覺這個(gè)結(jié)果并不能接受啊,禁止document 的touchmove都不能禁止?jié)L動(dòng)的嗎?
進(jìn)一步的探索后發(fā)現(xiàn)原因竟是這個(gè)屬性
passive addEventListener第三個(gè)參數(shù)中傳入
原來是瀏覽器做的一些優(yōu)化,chrome passive-event-listeners
Passive Event Listeners是Chrome提出的一個(gè)新的瀏覽器特性:Web開發(fā)者通過一個(gè)新的屬性passive來告訴瀏覽器,當(dāng)前頁面內(nèi)注冊的事件監(jiān)聽器內(nèi)部是否會(huì)調(diào)用preventDefault函數(shù)來阻止事件的默認(rèn)行為,以便瀏覽器根據(jù)這個(gè)信息更好地做出決策來優(yōu)化頁面性能。當(dāng)屬性passive的值為true的時(shí)候,代表該監(jiān)聽器內(nèi)部不會(huì)調(diào)用preventDefault函數(shù)來阻止默認(rèn)滑動(dòng)行為,Chrome瀏覽器稱這類型的監(jiān)聽器為被動(dòng)(passive)監(jiān)聽器。
知道問題就好說了,給addEventListener傳入第三個(gè)參數(shù)
document.addEventListener('touchmove', function (event) { event.preventDefault() }, { passive: false })
大功告成! 突然想到,如果浮層中還需要滾動(dòng)那就不GG了! so,是不是可以有選擇性的禁止?jié)L動(dòng)(在浮層中元素滾動(dòng)到最頂部或者最底部之后禁止?jié)L動(dòng))。 單獨(dú)處理浮層中需要滾動(dòng)的元素;
targetElement.ontouchmove = function (event) { const clientY = event.targetTouches[0].clientY - initialClientY if (targetElement && targetElement.scrollTop === 0 && clientY > 0) { return preventDefault(event) } if (targetElement && (targetElement.scrollHeight - 1 - targetElement.scrollTop <= targetElement.clientHeight) && clientY < 0) { return preventDefault(event) } event.stopPropagation() return true }
這個(gè)方案在ios中完美實(shí)現(xiàn),但是在 android中還是有一點(diǎn)問題;浮層內(nèi)容拉到最頂部或者最底部的時(shí)候依然會(huì)帶動(dòng)頁面的內(nèi)容有一定程度的移動(dòng)。
終極方案來啦!
tua-body-scroll-lock即是在ios、android和PC各個(gè)端單獨(dú)處理,保證在每個(gè)端都可以實(shí)現(xiàn)完美的效果!
安裝
$ npm i -S tua-body-scroll-lock
# OR
$ yarn add tua-body-scroll-lock
使用
移動(dòng)端
import { lock, unlock } from 'tua-body-scroll-lock' // 禁止滑動(dòng)后還需要內(nèi)部可以滾動(dòng)的元素(針對(duì)移動(dòng)端ios處理) const targetElement = document.querySelector("#someElementId"); lock(targetElement) unlock(targetElement)
PC端
tips: PC端不需要targetElement, 不傳targetElement也不想要控制臺(tái)提示可以傳null
import { lock, unlock } from 'tua-body-scroll-lock' lock() unlock()
以上所述是小編給大家介紹的滑動(dòng)穿透(鎖body)詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- 簡單通用的JS滑動(dòng)門代碼
- javascript 通用滑動(dòng)門tab類
- js自動(dòng)滑動(dòng)+鼠標(biāo)滑動(dòng)區(qū)域
- js實(shí)現(xiàn)touch移動(dòng)觸屏滑動(dòng)事件
- 使用原生js封裝webapp滑動(dòng)效果(慣性滑動(dòng)、滑動(dòng)回彈)
- 博客側(cè)邊欄模塊跟隨滾動(dòng)條滑動(dòng)固定效果的實(shí)現(xiàn)方法(js+jquery等)
- js實(shí)現(xiàn)滑動(dòng)觸屏事件監(jiān)聽的方法
- js實(shí)現(xiàn)支持手機(jī)滑動(dòng)切換的輪播圖片效果實(shí)例
- 淺談移動(dòng)端之js touch事件 手勢滑動(dòng)事件
- JS實(shí)現(xiàn)自動(dòng)輪播圖效果(自適應(yīng)屏幕寬度+手機(jī)觸屏滑動(dòng))
相關(guān)文章
Vue拖動(dòng)截圖功能的簡單實(shí)現(xiàn)方法
最近項(xiàng)目上要做一個(gè)車牌識(shí)別的功能,就需要做拖動(dòng)截圖功能了,因?yàn)榍岸问莢ue,所以下面這篇文章主要給大家介紹了關(guān)于Vue拖動(dòng)截圖功能的簡單實(shí)現(xiàn)方法,需要的朋友可以參考下2021-07-07Vue按回車鍵進(jìn)行搜索的實(shí)現(xiàn)方式
這篇文章主要介紹了Vue按回車鍵進(jìn)行搜索的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01vue 折疊展示多行文本組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue 折疊展示多行文本組件,自動(dòng)根據(jù)傳入的expand判斷是否需要折疊,非常完美,文章通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10vue?elementui動(dòng)態(tài)添加el-input實(shí)例代碼
最近遇到一個(gè)新的需求,需要?jiǎng)討B(tài)添加el-input,這篇文章主要給大家介紹了關(guān)于vue?elementui動(dòng)態(tài)添加el-input的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式
本文通過示例代碼介紹了vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式,通過場景分析介紹了vue3使用組合式api將時(shí)間戳格式轉(zhuǎn)換成時(shí)間格式(2023年09月28日 10:00),感興趣的朋友一起看看吧2023-12-12vue3.0關(guān)閉eslint校驗(yàn)的3種方法詳解
這篇文章主要給大家介紹了關(guān)于vue3.0關(guān)閉eslint校驗(yàn)的3種方法,在實(shí)際開發(fā)過程中,eslint的作用不可估量,文中將關(guān)閉的方法介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06