近期項目中使用iScroll遇到一個問題,在設定wrapper為橫向滾動時,如果你手指放在該區域,將無法拉動頁面,也就是說該區域取消了默認事件。這個體驗是實在是無法接受,特別是頁面中有多個橫向滾動區域時,很容易觸碰到這種區域,這時用戶將覺得頁面很卡。
Google搜了一下,看來很多人都為這個問題而煩惱。有高人給出了解決方案,在這里可以找到。
代碼如下:
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(); }, 它默認是直接取消默認事件。
到這里的時候感覺就不錯了。但是不要高興的太早。
上下滑動橫向滾動區域,頁面確實可以滾動了,但在多體驗了幾次頁面之后,又出現了一個問題。
先左右滑動該區域,滾動停止后再按住該區域想滾動頁面,你會發現它還是不能滾動頁面,這時你再點擊一次該區域,這時可以了。這相對於你需要觸摸2次才能滾動頁面, 這樣的行為還是讓人無法接受。
經過多翻測試,我把問題鎖定到absDistX/Y上。最后發現,在左右滑動之后absDistX/Y的值不會重置,第二次滑動該區域時執行onBeforeScrollStart事件,里面absDistX/Y值是上一次的值,所以程序還是阻止了頁面滾動。
解決方法如下:
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?其實是為了防止誤判斷,太敏感也不好,有時候你只是想左右滑動雖然滑動的角度有點朝上或朝下。
Ok,現在終於爽了,想怎么滑都行。體驗一下!