阻止移動端瀏覽器下拉橡皮筋效果(下拉滾動露底)


前言

最近項目有個需求:需要移動端瀏覽器下的橡皮筋效果,但是頁面內部的存在div框需要存在滾動。由此,遇到的問題與解決過程,記錄如下。

聲明:此處只討論js控制部分,css的設置(例:overflow的設置等)

第一步阻止橡皮筋效果

簡單粗暴的解決法,阻止瀏覽器滑動的默認行為

document.body.addEventListener('touchmove', (e) => {
  e.preventDefault();
});

這里需要說明下,在IOS11.3下此寫法不能達到預期效果,需要如下代碼

document.body.addEventListener('touchmove', (e) => {
  e.preventDefault();
}, { passive: false });

關於 passive: false 參考文章 passive 的事件監聽器,關於IOS11.3下解釋參考文章ios11.3 橡皮筋效果

至此解決了阻止移動端瀏覽器的橡皮筋效果

保證內部盒子的滾動效果

聲明:這里主要討論垂直滑動

討論

  1. 需要某個盒子(div)可以滑動,那么就不能阻止該盒子以及該盒子后代元素的默認行為(touchmove的滾動行為),所以我們需要識別盒子元素及其后代元素,不執行阻止其默認行為的操作
  2. 當滾動元素到達頂部時繼續向上滑時,同樣需要阻止其默認事件。滾動到底部時,繼續向下滾動也許阻止其默認行為。

綜上討論,首先判斷touch事件觸發元素是否為滾動元素及其后代元素,若是則阻止默認事件,若否判斷為頂部且向上滑或者為底部且向下滑。上代碼

let startY = 0;
const scrollBox = document.querySelector('.scroll-box');

document.body.addEventListener('touchstart', (e) => {
  startY = e.touches[0].pageY;
}, { passive: false });

document.body.addEventListener('touchmove', (e) => {
  const moveY = e.touches[0].pageY;
  const top = scrollBox.scrollTop;
  const ch = scrollBox.clientHeight;
  const sh = scrollBox.scrollHeight;
  if (!isChildTarget(e.target, scrollBox)) {
    e.preventDefault();
  } else if ((top === 0 && moveY > startY) || (top + ch === sh && moveY < startY)) {
    e.preventDefault();
  }
}, { passive: false });

到這里就差不多結束了,對於函數 isChildTarget 如下:

function isChildOf(child, parent, justChild = flase) { 
  // justChild為true則只判斷是否為子元素,若為false則判斷是否為本身或者子元素 默認為false
  let parentNode;
  if (justChild) {
    parentNode = child.parentNode;
  } else {
    parentNode = child;
  }
  
  if (child && parent) {
    while (parentNode) {
      if (parent === parentNode) {
        return true;
      }
      parentNode = parentNode.parentNode;
    }
  }
  return false;
}

這下真的結束了。

如有問題, 歡迎交流學習。
如需轉載請注明出處 本文地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM