Swiper如何实现内容超出滑动

  对于使用Swiper实现整屏滑动的页面,如果某一页内容超过一屏高度,超出部分将无法通过滚动条下滑查看,即便我们设置了overflow:scroll

  如果我们单纯的通过手势判断滑倒上一页/下一页,在一些浏览器表现不佳,所以我们得滑动到有滚动条的部分时,再去触发我们的相关事件。


  最后一页的iPhone专区,其页面内容超过一屏高度,即使我们使出吃奶的劲去滑,超出部分将无法查看到,如图所示:
Image text
其Css如下:

1
2
3
4
5
.p-other{
position: relative;
height: 100%;
overflow-y: scroll;
}

  这是为什么呢,因为Swiper注册了touchstart,touchmove,和touchend事件,当手指在屏幕上滑动时,使用CSS3的transform来实时设置viewport的位置,比如要显示第二个页面,就设置viewport的transform:translate3d(100%,0,0)即可, 在这里使用translate3d来代替translateX,translate3d可以主动开启手机GPU加速渲染,页面滑动更流畅。
  所以当我们滑到最后一页时,Swiper监听到了touchstart,touchmove等,在改变其translate3d值,所以无法正常查看到超出该屏幕的内容。如下图所示,通过Chrome观察,我们可以看到每一次滑屏,都是translate3d值的改变。
Image text

  我们想要的效果是,超出的内容不受影响,出现滚动条,正常上下话查看内容;并且滑到底部/顶部时,仍然可以切换下一屏/上一屏。
  在这种情况,我们祭出一段利器,在js中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var startScroll, touchStart, touchCurrent;
page_swiper.slides.on('touchstart', function (e) {
startScroll = this.scrollTop;
touchStart = e.targetTouches[0].pageY;
}, true);
page_swiper.slides.on('touchmove', function (e) {
touchCurrent = e.targetTouches[0].pageY;
var touchesDiff = touchCurrent - touchStart; //判断滑动方向
var slide = this;
var onlyScrolling =
( slide.scrollHeight > slide.offsetHeight ) && //如果滑动到存在滚动条的结构时,此判断为true
(
( touchesDiff < 0 && startScroll === 0 ) || //从顶部滚动到底部
( touchesDiff > 0 && startScroll === ( slide.scrollHeight - slide.offsetHeight ) ) || //从底部滚动到顶部
( startScroll > 0 && startScroll < ( slide.scrollHeight - slide.offsetHeight ) ) //从中间开始
);
if (onlyScrolling) {
e.stopPropagation(); //终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。
}
}, true);

  其中核心是判断onlyScrolling的状态,当滑动到有滚动条的部分时,slide.scrollHeight > slide.offsetHeighttrue,否则为false
当滑到需要Swiper切换的临界点时,如下图所示代码为false,在滚动中间区域时,为true
  所以当onlyScrolling 为true时,可以知道用户在浏览超出滚动的内容,当达到临界点想离开时,onlyScrolling为false,不再阻止Swiper滑动,整屏可自由滑动。
  当onlyScrollingtrue时,阻止Swiper改变transform值,使超出滚动部分的内容可以正常浏览。如下图所示:
Image text
  至此,我们大功告成!