摘要:背景由于移動(dòng)端原生滾動(dòng)的局限性以及兼容性,部分特定場(chǎng)景的需求無(wú)法滿足。示例模擬滾動(dòng)知識(shí)點(diǎn)通過(guò)移動(dòng)端的系列事件觸發(fā)模擬滾動(dòng),獲取手指滑動(dòng)的偏移量,進(jìn)而改變來(lái)進(jìn)行位置偏移。
背景
由于移動(dòng)端原生滾動(dòng)的局限性以及兼容性,部分特定場(chǎng)景的需求無(wú)法滿足。例如,筆者最近就接了一個(gè)需求:整個(gè)頁(yè)面分為三塊,每塊內(nèi)容的高度不等(但都超過(guò)一屏),要求滾動(dòng)到內(nèi)容的臨界點(diǎn)有一個(gè)停頓的效果,下拉可以看到下一塊的部分內(nèi)容,滿足條件則滑到下一塊內(nèi)容。這種場(chǎng)景下,原生的滾動(dòng)根本無(wú)法支持。因此,本文的主角就亮相了:模擬滾動(dòng),即盡可能的模擬原生滾動(dòng),但是又提供了一些擴(kuò)展,滿足復(fù)雜場(chǎng)景的需求。
本文將從模擬滾動(dòng)需要實(shí)現(xiàn)的功能、技術(shù)分析和方案來(lái)進(jìn)行闡述,通讀本文,讀者將對(duì)模擬滾動(dòng)的常見(jiàn)功能和技術(shù)要點(diǎn)有一定了解。
示例:模擬滾動(dòng)
知識(shí)點(diǎn)通過(guò)移動(dòng)端的touch系列事件觸發(fā)模擬滾動(dòng),獲取手指滑動(dòng)的偏移量,進(jìn)而改變translateY來(lái)進(jìn)行位置偏移。
滾動(dòng)容器滾動(dòng)容器擁有高度,滾動(dòng)區(qū)域的高度大于滾動(dòng)容器,在滾動(dòng)時(shí),我們對(duì)滾動(dòng)區(qū)域進(jìn)行偏移,以達(dá)到滾動(dòng)的視覺(jué)效果。
通過(guò)滾動(dòng)區(qū)域的高度可以通過(guò)offsetHeight獲取,但是在以下情況下會(huì)遠(yuǎn)遠(yuǎn)小于實(shí)際高度。
內(nèi)聯(lián)樣式:在DOM節(jié)點(diǎn)生成時(shí),樣式還未渲染完成,此時(shí)獲得的高度是默認(rèn)樣式的高度,待樣式渲染完成后,高度可能會(huì)有變化
圖片高度:img節(jié)點(diǎn)的高度開(kāi)始是0,在圖片加載完成時(shí),才會(huì)等于圖片高度,因此這里也會(huì)存在誤差
慣性滾動(dòng)我們知道,為了讓滾動(dòng)更加流暢,原生的滾動(dòng)會(huì)有一個(gè)慣性滾動(dòng)的效果,即手指快速滑動(dòng)松開(kāi)后,滾動(dòng)區(qū)域會(huì)繼續(xù)滾動(dòng)一段距離后停止。
為了實(shí)現(xiàn)這個(gè)功能,我們需求知道手指滑動(dòng)的速度,根據(jù)比率計(jì)算目標(biāo)滾動(dòng)位置,然后驅(qū)動(dòng)滾動(dòng),讓其到達(dá)目標(biāo)位置。
這里筆者嘗試了兩種方案:
通過(guò)requestAnimationFrame不斷進(jìn)行偏移,直到到達(dá)目標(biāo)位置
使用transition進(jìn)行過(guò)渡,設(shè)置動(dòng)畫(huà)曲線讓其到達(dá)目標(biāo)位置
筆者對(duì)比了兩種方案,最終選擇了方案2,原因是transition過(guò)渡會(huì)更加的流暢,而requestAnimationFrame會(huì)有略微的卡頓,但是transition過(guò)渡,我們實(shí)時(shí)觸發(fā)滾動(dòng)事件時(shí),不好拿到其當(dāng)前的位置,查閱了一些資料,筆者最終找到了解決方法,即getComputedStyle,這個(gè)API可以拿到當(dāng)前頁(yè)面渲染的實(shí)時(shí)樣式,也就是說(shuō),哪怕它處于過(guò)渡動(dòng)畫(huà)中,我們可以實(shí)時(shí)拿到它的真實(shí)位置。
邊界回彈當(dāng)滾動(dòng)超出邊界時(shí),通常我們還可以讓其繼續(xù)滾動(dòng),但是這時(shí)候會(huì)設(shè)置阻礙,即滾動(dòng)速度慢下來(lái),當(dāng)滾動(dòng)停止時(shí),我們?cè)賹⑵渥Щ氐竭吔缇€。我們可以通過(guò)監(jiān)聽(tīng)transitionend事件來(lái)判斷慣性滾動(dòng)停止,這里的技術(shù)點(diǎn)不做過(guò)多分析,感興趣可以在文末中的源碼找答案。
默認(rèn)行為通常情況下,我們需要阻止瀏覽器的默認(rèn)行為(如滾動(dòng)),但是這樣也會(huì)誤殺一些我們需要的默認(rèn)行為(如超鏈接跳轉(zhuǎn)、輸入框聚焦)。
解決方法很簡(jiǎn)單,在touchstart觸發(fā)時(shí),我們判斷一下目標(biāo)節(jié)點(diǎn)是否需要阻止默認(rèn)行為,比如說(shuō)tagName=INPUT,我們不阻止默認(rèn)行為。
點(diǎn)擊事件默認(rèn)行為被阻止,綁定在子節(jié)點(diǎn)上的點(diǎn)擊事件就無(wú)法觸發(fā)了,因此這里我們需要判斷一下是否需要觸發(fā)點(diǎn)擊事件??梢酝ㄟ^(guò)touch系列事件模擬點(diǎn)擊行為,然后通過(guò)document.createEvent("Event")來(lái)主動(dòng)觸發(fā)click事件。
滾動(dòng)指示器在滾動(dòng)區(qū)域中,通常在右側(cè)會(huì)有一個(gè)指示器,用于查看當(dāng)前在整個(gè)內(nèi)容區(qū)塊的大概位置。
為了方便使用,筆者注冊(cè)了一系列的鉤子,方便使用者調(diào)用,scroll鉤子就是其中之一,在滾動(dòng)的時(shí)候它會(huì)實(shí)時(shí)觸發(fā),在這里就派上用場(chǎng)了。我們通過(guò)scroll鉤子改變指示器的位置,唯獨(dú)要注意的是滾動(dòng)超出邊界時(shí),指示器會(huì)變短然后恢復(fù)。
@axe/scroller基于以上知識(shí)點(diǎn)和技術(shù)分析,筆者寫(xiě)了一個(gè)模擬滾動(dòng)js庫(kù)(無(wú)任何依賴):https://github.com/ansenhuang/axe/blob/master/packages/scroller/README.md
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/97644.html
摘要:還會(huì)有一個(gè)性能上的問(wèn)題就是當(dāng)頁(yè)面的列表過(guò)長(zhǎng),元素過(guò)多時(shí),在模擬滾動(dòng),下拉刷新這段時(shí)間內(nèi),頁(yè)面也會(huì)有卡頓現(xiàn)象,這里采取了一個(gè)優(yōu)化策略即列表較長(zhǎng)時(shí)數(shù)量較多時(shí),在觸發(fā)下拉刷新的時(shí)機(jī)時(shí)將頁(yè)面視窗之外的元素隱藏或者存放在里面。 移動(dòng)web滾動(dòng)問(wèn)題 在移動(dòng)端如果使用局部滾動(dòng),意思就是我們的滾動(dòng)在一個(gè)固定寬高的div內(nèi)觸發(fā),將該div設(shè)置成overflow:scroll/auto;來(lái)形成div內(nèi)部的...
摘要:同時(shí),請(qǐng)?jiān)谄渌苿?dòng)端瀏覽器也這么處理,不要只對(duì)蘋(píng)果做這些處理。蘋(píng)果對(duì)于虎頭蛇尾的做法真讓人頭疼,這作風(fēng)跟巨硬真像。 轉(zhuǎn)載請(qǐng)注明英文原文及譯文出處 原文地址:Issues with position fixed & scrolling on iOS 原文作者:Remy Sharp譯文地址:移動(dòng)端 fixed 和 scroll 問(wèn)題 譯文作者:鎏金圣手火麒麟 最近在做iOS端的H5頁(yè)面...
摘要:同時(shí),請(qǐng)?jiān)谄渌苿?dòng)端瀏覽器也這么處理,不要只對(duì)蘋(píng)果做這些處理。蘋(píng)果對(duì)于虎頭蛇尾的做法真讓人頭疼,這作風(fēng)跟巨硬真像。 轉(zhuǎn)載請(qǐng)注明英文原文及譯文出處 原文地址:Issues with position fixed & scrolling on iOS 原文作者:Remy Sharp譯文地址:移動(dòng)端 fixed 和 scroll 問(wèn)題 譯文作者:鎏金圣手火麒麟 最近在做iOS端的H5頁(yè)面...
摘要:很多時(shí)候我們?cè)谏献鰟?dòng)畫(huà)一般都是選擇滾動(dòng)事件來(lái)觸發(fā)。而在移動(dòng)端的瀏覽器或中,滾動(dòng)事件的觸發(fā)頻率也是不同的。在中在視圖的滾動(dòng)過(guò)程中,事件不會(huì)被觸發(fā)在滾動(dòng)結(jié)束后,才會(huì)觸發(fā)和不受此影響。但是滾動(dòng)觸發(fā)事件與滾動(dòng)距離以及完成的時(shí)間有關(guān)。 很多時(shí)候我們?cè)趙eb上做動(dòng)畫(huà)一般都是選擇滾動(dòng)事件來(lái)觸發(fā)。因?yàn)閯?dòng)畫(huà)需要判斷是否處于視口內(nèi),或者是否到達(dá)某個(gè)臨界點(diǎn)。而滾動(dòng)在不同的瀏覽器中,不同操作系統(tǒng)中的實(shí)現(xiàn)都有不...
閱讀 1768·2021-09-23 11:21
閱讀 2452·2021-09-07 10:13
閱讀 902·2021-09-02 10:19
閱讀 1186·2019-08-30 15:44
閱讀 1785·2019-08-30 13:18
閱讀 1964·2019-08-30 11:15
閱讀 1192·2019-08-29 17:17
閱讀 2068·2019-08-29 15:31