最近一直在想怎么解决移动端使用局部滚动解决ios不支持position:fixed后产生的问题。虽然之前写的两篇文章中都有讲到,但这两天在整理弹窗插件的时候又想到了一些问题,花了不少时间,总算是弄出了个结果。下面,就把这成果跟大家分享一下吧。
首先,我们看看问题点在哪:
1、根本在于ios设备对position:fixed的支持不理想,为了兼容这一点,需要使用局部滚动代替全局滚动;
2、在支持溢出滑动的浏览器里,局部滚动过程中很容易会出现直接拖动整个页面的情况;
3、在安卓设备中,局部滚动区域内的input标签在获得焦点后会被弹出的软键盘遮挡住。
另外,如果局部滚动布局能较完美地解决问题,那么,弹窗时也能直接通过overflow:hidden来禁止页面的滚动了。
综合分析这些问题,我想出了一套解决方案。
解决思路其实挺简单的,既然溢出拖动的机制是滚动条到达顶部或底部后继续往下或往上滑动,那么,我们不让滚动条到达顶部或底部就可以了。
var rinyScroll=function(options){
this.options=options;
this.el=document.getElementById(this.options.el);
};
rinyScroll.prototype.scroll=function(){
if(this.el.scrollTop==0){
this.el.scrollTop=1;
};
this.el.onscroll=function(){
//由于部分设备中scrollTop与clientHeight之和不完全等于scrollHeight(一般会少于),因此+1再判断是否大于等于。
if(this.scrollTop+this.clientHeight+1>=this.scrollHeight){
this.scrollTop=this.scrollHeight-this.clientHeight-1;
}else if(this.scrollTop==0){
this.scrollTop=1;
};
};
};
rinyScroll.prototype.input=function(){
var _this=this.el;
_this.addEventListener('click',function(e){
var screenNowH=document.documentElement.clientHeight,inputT=e.target.offsetTop,wrapScrollTop=_this.scrollTop;
window.onresize=function(){
var screenH=document.documentElement.clientHeight;
//判断窗口大小改变是否为关闭软键盘,或input的所处位置是否高于软键盘打开后窗口中间以上
if(screenH==screenNowH || screenH+wrapScrollTop>=inputT+(screenH/2)){
return;
};
var t=inputT-(screenH/2);
_this.scrollTop=t;
};
},false);
};
这套代码主要解决了局部滚动容易造成整个页面拖动以及局部滚动区域内的input标签在获取焦点后被弹出的软键盘遮挡住的问题,可以直接复制回去实例化使用。
//el为局部滚动元素的id
var myScroll=new rinyScroll({
el:'box'
});
myScroll.scroll();
myScroll.input();
这套解决方案虽然不能称之为完美,但适用范围广,可复用性强,也便于页面的后期维护。就个人测试结果来看,比起那些禁止默认事件的做法要好很多。
当然,各位还有什么更好的做法不妨分享一下,让大家学习学习。