<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          移動端滾動穿透與滾動溢出解決方案

          共 2397字,需瀏覽 5分鐘

           ·

          2022-03-18 11:20

          滾動穿透

          滾動穿透.gif

          問題描述

          在移動端 WEB 開發(fā)的時候(小程序也雷同),如上錄屏所示,如果頁面超過一屏高度出現(xiàn)滾動條時,在 fixed 定位的彈窗遮罩層上進(jìn)行滑動,它下面的內(nèi)容也會跟著一起滾動,看起來好像事件穿透到下面的DOM元素上一樣,我們姑且稱之為滾動穿透。

          問題原因

          能夠猜想是文檔(document)的滾動事件被觸發(fā)了,如果能禁用滾動事件就好辦了。

          案例偽代碼

          class="btn">點擊出現(xiàn)彈窗</div>


          ??div>
          ??<div?class="popup-body?popup-bottom">
          ????<div?class="header">我是標(biāo)題div>

          ????<div?class="content">
          ??????<div>0div>
          ????????
          ??????<div>1div>
          ??????<div>...div>
          ????div>
          ??div>
          </div>
          .popup-mask?{
          ??background-color:?rgba(0,?0,?0,?0.5);
          ??position:?fixed;
          ??z-index:?998;
          ??top:?0;
          ??bottom:?0;
          ??left:?0;
          ??right:?0;
          }

          .popup-body?{
          ??padding:?0?50px?40px;
          ??background-color:?#fff;
          ??position:?fixed;
          ??z-index:?999;
          }

          ? 解決方案A (touch-action)

          默認(rèn)情況下,平移(滾動)和縮放手勢由瀏覽器專門處理,但是可以通過 CSS 特性 touch-action 來改變觸摸手勢的行為。摘取幾個 touch-action 的值如下。

          描述
          auto啟用瀏覽器處理所有平移和縮放手勢。
          none禁用瀏覽器處理所有平移和縮放手勢。
          manipulation啟用平移和縮放手勢,但禁用其他非標(biāo)準(zhǔn)手勢,例如雙擊縮放。
          pinch-zoom啟用頁面的多指平移和縮放。

          于是在 popup 元素上設(shè)置該屬性,禁用元素(及其不可滾動的后代)上的所有手勢就可以解決該問題了。

          .popup?{
          ??touch-action:?none;
          }

          Note: [無障礙設(shè)計] 阻止頁面縮放可能會影響視力不佳的人閱讀和理解頁面內(nèi)容,不過小程序本身好像就不可以縮放!

          ? 解決方案B (event.preventDefault)

          來自 W3C 的一個標(biāo)準(zhǔn)。

          描述.jpg

          大意是說,在 touchstart 和 touchmove 事件中調(diào)用 preventDefault 方法可以阻止任何關(guān)聯(lián)事件的默認(rèn)行為,包括鼠標(biāo)事件和滾動。

          因此我們可以這樣處理。
          Step 1、監(jiān)聽彈窗最外層元素(popup)的 touchmove 事件并阻止默認(rèn)行為來禁用所有滾動(包括彈窗內(nèi)部的滾動元素)。
          Step 2、釋放彈窗內(nèi)的滾動元素,允許其滾動:同樣監(jiān)聽 touchmove 事件,但是阻止該滾動元素的冒泡行為(stopPropagation),使得在滾動的時候最外層元素(popup)無法接收到 touchmove 事件。

          const?popup?=?document.querySelector('.popup')
          const?scrollBox?=?document.querySelector('.content')

          popup.addEventListener('touchmove',?(e)?=>?{
          ??//?Step?1:?阻止默認(rèn)事件
          ??e.preventDefault()
          })

          scrollBox.addEventListener('touchmove',?(e)?=>?{
          ??//?Step?2:?阻止冒泡
          ??e.stopPropagation()
          })

          滾動溢出

          滾動溢出.gif

          問題描述

          如上錄屏所示,彈窗內(nèi)也含有滾動元素,在滾動元素滾到底部或頂部時,再往下或往上滾動,也會觸發(fā)頁面的滾動,這種現(xiàn)象稱之為滾動鏈(scroll chaining), 但是感覺滾動溢出(overscroll)這個名字更言辭達(dá)意。

          ? 解決方案A (overscroll-behavior)

          overscroll-behavior 是 CSS 的一個特性,允許控制瀏覽器滾動到邊界的表現(xiàn),它有如下幾個值。

          描述
          auto默認(rèn)效果,元素的滾動可以傳播到祖先元素。
          contain阻止?jié)L動鏈,滾動不會傳播到祖先元素,但是會顯示節(jié)點自身的局部效果。例如 Android 上過度滾動的發(fā)光效果或 iOS 上的橡皮筋效果。
          none與 contain 相同,但是會阻止自身的過度效果。

          所以可以這樣解決問題:

          .content?{
          ??overscroll-behavior:?none;
          }

          簡潔干凈高性能,不過 Safari 全系不支持,兼容性如下,有沒有感覺 Safari 就是現(xiàn)代版的 IE(偶然聽路人說的)!

          ? 解決方案B (event.preventDefault)

          借用 event.preventDefault 的能力,當(dāng)組件滾動到底部或頂部時,通過調(diào)用 event.preventDefault 阻止所有滾動,從而頁面滾動也不會觸發(fā)了,而在滾動之間則不做處理。

          let?initialPageY?=?0

          scrollBox.addEventListener('touchstart',?(e)?=>?{
          ????initialPageY?=?e.changedTouches[0].pageY
          })

          scrollBox.addEventListener('touchmove',?(e)?=>?{
          ????const?deltaY?=?e.changedTouches[0].pageY?-?initialPageY
          ????
          ????//?禁止向上滾動溢出
          ????if?(e.cancelable?&&?deltaY?>?0?&&?scrollBox.scrollTop?<=?0)?{
          ????????e.preventDefault()
          ????}

          ????//?禁止向下滾動溢出
          ????if?(
          ????????e.cancelable?&&
          ????????deltaY?0?&&?
          ????????scrollBox.scrollTop?+?scrollBox.clientHeight?>=?scrollBox.scrollHeight
          ????)?{
          ????????e.preventDefault()
          ????}
          })

          解決方案完整 Demo

          https://github.com/Barrior/cases/blob/main/overscroll.html#L107-L143

          關(guān)于本文

          作者:Barrior

          https://segmentfault.com/a/1190000040675446

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
          ?》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩少妇在线 | 国产精品成人va在线观看在线 | www.青春草 | 99re视频在线 | 草比综合网 |