移动端项目经常碰到的一个问题是ios系统的橡皮筋效果处理,这个效果本身的体验还是挺不错的,但是当我们的应用出现遮罩层时,此时滑动页面,我们的预期是页面不进行滚动或者当前遮罩层内部滚动,而实际上滑动会触发橡皮筋效果,与预期不符。
这一次我们的移动端项目中毫不意外碰到了这个问题,通过一些实践,最终还算完美地解决了这个问题。处理方法的核心就是:监听遮罩层的’touchmove’事件,如果遮罩层不需要滑动,则直接阻止其默认行为;如果遮罩层需要滚动,则判断触发事件的‘target’元素是否属于遮罩层,不属于则直接阻止默认行为,属于则要判断元素滚动是否到达顶部或者底部,已到达顶部则阻止下拉,同理,到达底部则阻止上拉;而上拉下拉的判断,则通过元素‘touchstart’与‘touchmove’事件直接手指触摸的位置之差来判断。差值为负则上拉,为正则下拉。
在我的react移动端项目中,有一组下拉框组件需要进行滑动处理,其中有遮罩层不可滚动的,也有需要滚动的,具体实现是在‘componentWillReceiveProps’这个钩子函数中,依据传入的props值来判断遮罩层是否开启以及该组件是否需要滚动,具体代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45componentWillReceiveProps(nextProps) {
//nextProps.opened为true表示下拉框开启,出现遮罩层,stopMove为1表示不需要滚动
if(nextProps.opened && nextProps.stopMove===1){
this.stopTouchmove(this.refs.selectWrap);
}
else if(nextProps.opened){
element = this.refs.selectWrap; //遮罩层元素,element、startY、moveEndY为全局变量
if(element){
element.addEventListener('touchstart', this.onTouchStart); //监听touchstart事件,获取滑动初始值
element.addEventListener('touchmove', function (e) {
e.stopPropagation(); //阻止冒泡
moveEndY = e.changedTouches[0].pageY;
let Y = moveEndY - startY; //计算滚动差值
if(!e.target || e.target.nodeName!='LI'){ //所属行业和所在地区按照标签名判断是否能滚动
e.preventDefault();
}
else if(e.target.nodeName=='LI' &&e.target.parentNode &&e.target.parentNode.nodeName==='UL'){
let top = e.target.parentNode.scrollTop; //可滚动区域滚动高度
let showHeight = e.target.parentNode.clientHeight; //可滚动区域显示高度
let sumHeight = 0;
let Arr = e.target.parentNode.children;
for(let i=0;i<Arr.length;i++){ //计算可滚动区域总高度
sumHeight = sumHeight+ Arr[i].clientHeight;
}
if((top>=sumHeight-showHeight && Y<0) || (top===0 &&Y>0)){ //到底部禁止上拉,到顶部禁止下拉
e.preventDefault();
}
}
}, false);
}
}
//获取滑动初始值
onTouchStart = (e) => {
startY = e.touches[0].pageY;
};
//阻止滚动
stopTouchmove = (element)=>{
if(element){
element.addEventListener('touchmove', (e) => {
e.preventDefault();
}, false);
}
}
上面就是针对ios系统橡皮筋效果处理的全部内容,核心思想不变,就是阻止滑动事件的默认行为,使用的时候就得因地制宜,什么时候该阻止什么时候不阻止得视情况而定,具体问题具体分析即可。
另:移动端滚动效果通常是通过加‘overflow: auto;’实现,但是只加这个属性滚动会不流畅,因此通常需要在加一句‘-webkit-overflow-scrolling: touch;’,这样滚动效果就会很流畅了。