近期项目中使用iScroll遇到一个问题,在设定wrapper为横向滚动时,若是你手指放在该区域,将没法拉动页面,也就是说该区域取消了默认事件。这个体验是实在是没法接受,特别是页面中有多个横向滚动区域时,很容易触碰到这种区域,这时用户将以为页面很卡。html
Google搜了一下,看来不少人都为这个问题而烦恼。有高人给出了解决方案,在这里能够找到。app
代码以下:测试
myScroll = new iScroll('scrollpanel', { // other options go here... vScroll: false, onBeforeScrollStart: function ( e ) { if ( this.absDistX > (this.absDistY + 5 ) ) { // user is scrolling the x axis, so prevent the browsers' native scrolling e.preventDefault(); } } });
重写onBeforeScrollStart事件,判断touch的滑动距离,只在横向滑动距离大于竖向滑动距离时(也就是左右滑动时)才取消默认事件,这样就不影响页面滚动了。看iScroll源码,onBeforeScrollStart: function (e) { e.preventDefault(); }, 它默认是直接取消默认事件。this
到这里的时候感受就不错了。可是不要高兴的太早。spa
上下滑动横向滚动区域,页面确实能够滚动了,但在多体验了几回页面以后,又出现了一个问题。code
先左右滑动该区域,滚动中止后再按住该区域想滚动页面,你会发现它仍是不能滚动页面,这时你再点击一次该区域,这时能够了。这相对于你须要触摸2次才能滚动页面, 这样的行为仍是让人没法接受。htm
通过多翻测试,我把问题锁定到absDistX/Y上。最后发现,在左右滑动以后absDistX/Y的值不会重置,第二次滑动该区域时执行onBeforeScrollStart事件,里面absDistX/Y值是上一次的值,因此程序仍是阻止了页面滚动。blog
解决方法以下:事件
myScroll = new iScroll('scrollpanel', { // other options go here... hScroll: true, onBeforeScrollStart: function ( e ) { if ( this.absDistX > (this.absDistY + 5 ) ) { // user is scrolling the x axis, so prevent the browsers' native scrolling e.preventDefault(); } }, //解决第一次没法滑动的问题 onTouchEnd: function () { var self = this; if (self.touchEndTimeId) { clearTimeout(self.touchEndTimeId); } self.touchEndTimeId = setTimeout(function () { self.absDistX = 0; self.absDistY = 0; }, 600); } });
在onTouchEnd里面作处理,每次滑动以后都重置absDistX/Y的值。为何要使用setTimeout?实际上是为了防止误判断,太敏感也很差,有时候你只是想左右滑动虽然滑动的角度有点朝上或朝下。get
Ok,如今终于爽了,想怎么滑都行。