移动端内滚动与外滚动

概述

在做移动端开发的时候,经常会遇到内滚动与外滚动的问题,下面我对这方面好好的总结了一下,供以后开发时参考,相信对其他人也有用。

参考资料:关于height、offsetheight、clientheight、scrollheight、innerheight、outerheight的区别一览

内滚动与外滚动

关于移动端的内滚动和外滚动,有如下结论:

  1. 如果如果内滚动是外滚动的一部分(比如正常页面里面有一个可以滚动的容器),那么内滚动在滚动时,不会触发外滚动,只有在滚动到顶部或者底部的时候,才会触发外滚动。
  2. 如果内滚动是一个弹层或者蒙版,那么内滚动会触发外滚动。(这就是滚动穿透,类似于点击穿透)

带来的问题

1.如果内滚动是外滚动的一部分,那么滚动的体验本身还是不错的。但有时需要在内滚动到顶部或者底部的时候不触发外滚动

2.如果内滚动是一个弹层或者蒙版,这个时候体验就很差了,有时候我们需要不论在什么时候,内滚动都不触发外滚动

解决方法

对于问题2,一般是用swiper.js插件或者slimeScroll插件来解决的。

对于问题1,可以手动解决,下面说下解决思路。

用到的概念

  • pageY: 表示相对于容器,鼠标指针的位置。(用来判断鼠标是向上滑动还是向下滑动)
  • scrollHeight: 表示整个元素的高度,包括了滚动内容的高度。
  • clientHeight: 表示元素的可视高度,不包括滚动内容,边框或边距。
  • offsetheight: 表示元素的高度,包括padding和边框。
  • scrollTop: 表示滚动条滚动的距离。

所以有如下关系:

scrollHeight = clientHeight + scrollTop

如果没有边框的话,offsetheight = clientHeight,那么也有:

scrollHeight = offsetheight + scrollTop

根据上面的等式,可以判断滑块是否滑到顶部或者底部。

jquery的pageY

一般来说,pageY是通过event.pageY来获取的,但是对于有些版本的jquery,需要用下面的代码获取pageY:

event.originalEvent.targetTouches[0].pageY

代码

那么检测顶部的逻辑是:

  1. scrollTop < 1
  2. 手指仍旧向上滑动(注意,如果向下滑动,则不阻止滑动事件)

那么检测底部的逻辑是:

  1. scrollHeight - (offsetheight + scrollTop) < 1
  2. 手指仍旧向下滑动(注意,如果向下滑动,则不阻止滑动事件)

最后怎么来阻止滑动呢?用e.preventDefault()即可。

代码很好理解,就直接贴出来了:

//上下边缘检测
setScroll: (select) => {
  let $ele = $(select),
      eleStart;
  $ele.on('touchstart', function(e) {
    eleStart = e.originalEvent.targetTouches[0].pageY;
  });
  $ele.on('touchmove', function(e) {
    let eleTouch = e.originalEvent.targetTouches[0].pageY - boxInfoStart,
        scrollVal1 = $ele.scrollTop(),
        scrollVal2 = $ele[0].scrollHeight - $ele[0].offsetHeight - $ele.scrollTop();
    //向上滑到顶部
    if(eleTouch>0 && scrollVal1 < 1) {
      e.preventDefault();
    }
    //向下滑到底部
    if(eleTouch<0 && scrollVal2 < 1) {
      e.preventDefault();
    }
  });
},

其它

上面的代码还可以用于解决,移动端拖动页面顶部或者底部会出现黑块,的问题。

猜你喜欢

转载自www.cnblogs.com/yangzhou33/p/9236577.html