阻止移动端浏览器下拉橡皮筋效果(下拉滚动露底)

前言

最近项目有个需求:需要移动端浏览器下的橡皮筋效果,但是页面内部的存在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;
}

这下真的结束了。

如有问题, 欢迎交流学习。
如需转载请注明出处 本文地址

猜你喜欢

转载自www.cnblogs.com/dongcanliang/p/8946495.html
今日推荐