一、问题描述
在web的移动端页面,写了一个弹框;弹框内容较长,所以弹框内有滑动效果;在滑动的时候,当你想滑动的是弹框内的窗体,但是偶尔外层窗体跟着滑动,两个窗体相互影响。
二、产生原因
为什么说偶尔呢,弹框的窗体滑动与外层父窗体的滑动有先后顺序,一般是弹框窗体滑动,滑动完之后,再滑动页面的时候,就变成了父窗体滑动(浏览器默认行为),但是这个时候,不想父窗体滑动, 希望用户操作的滑动跟父窗体没有关系,永远停留在自己写的弹框滑动操作中。
三、解决思路
阻止浏览器的默认行为。
四、具体实施步骤
监控弹框的触摸事件和滑动事件:
1. 监控触摸事件(ontouch)是为了判断手势是上拉还是下滑;
1)触摸开始时(ontouchstart)记录数值(data.start),触摸中(ontouchmove)也记录数值(data.move);开始时的数值减去触摸中的数值distanceY(data.start - data.move)与0比较,用来判断是上拉还是下滑;
2)distanceY>0,则为上拉,反之distanceY<0则为下滑;
2. 监控滑动事件(onscroll)是为了获取整个弹框窗体的长度(maxDistanceY)以及当前的滑动距离(scrollTop);
1)滑动距离(scrollTop)<=0时,则表示已经下滑到底了,这时候可以阻止浏览器默认行为,也就是继续滑动的时候,不让父窗体滑动;反之scrollTop>0的时候,也就是下滑的时候放开浏览器默认行为(因为不放开的话自己的弹框就划不动了)
2)用maxDistanceY(e.target.scrollHeight - e.target.offsetHeight)表示整个滑动的距离(也可以理解为弹框滑动窗体的长度),当scrollTop>=maxDistanceY时则表示已经下滑到底了。这时候又要阻止浏览器默认行为了;
五、总结归纳
1)上拉到底,阻止浏览器默认行为;
2)下滑到底,阻止浏览器默认行为;
3)只有阻止了浏览器默认行为,在弹框内滑动第二屏的时候,才不会跟父窗体相互影响。
六、代码如下
function stopPration() {
var scrollTop;
var distanceY;
var maxDistanceY;
var data = {start: 0, move: 0, end: 0};
var touchMoveDiv = document.getElementById('scrollPop');
touchMoveDiv.onscroll = function (e) {
scrollTop = e.target.scrollTop;
maxDistanceY = e.target.scrollHeight - e.target.offsetHeight;
}
touchMoveDiv.ontouchstart = function (e) {
data.start = e.pageY;
}
touchMoveDiv.ontouchmove = function (e) {
data.move = e.pageY;
distanceY = data.start - data.move;
if (distanceY > 0 && scrollTop >= maxDistanceY) {
e.preventDefault();
}
if (distanceY <= 0) {
if (scrollTop > 0) {
return true;
} else if (scrollTop <= 0 || (!scrollTop)) {
e.preventDefault();
}
}
}
}