iScroll橫向滾動區域沒法拉動頁面的解決方案

近期項目中使用iScroll遇到一個問題,在設定scroll-box爲橫向滾動時,若是你手指放在該區域,將沒法拉動頁面,也就是說該區域取消了默認事件。這個體驗是實在是沒法接受,這樣子照成沒法拉動頁面,查看滾動區域下面的內容。測試

Google了一會兒,有個高手給出瞭解決方案,參考地址:http://stackoverflow.com/questions/7800261/iscroll-with-native-scrolling-on-one-axisthis

思路以下:spa

咱們知道正常調用觸摸事件scroll是這樣子的  new iScroll("scroll-box",{hScrollbar:false,vScrollbar:false,vScroll:false};code

經過分析iScroll源碼發現 再拖動區域觸發 touchstart 或者 mousedown事件的時候會首先調用 _start(e);
blog

源碼流程:事件

//事件觸發
handleEvent: function (e) {
        var that = this;
        switch(e.type) {
            case START_EV:
                if (!hasTouch && e.button !== 0) return;
                that._start(e);
                break;
            case MOVE_EV: that._move(e); break;
            case END_EV:
            case CANCEL_EV: that._end(e); break;
            case RESIZE_EV: that._resize(); break;
            case 'DOMMouseScroll': case 'mousewheel': that._wheel(e); break;
            case TRNEND_EV: that._transitionEnd(e); break;
        }
    }
//觸發_start(e)
_start: function (e) {
        var that = this,
            point = hasTouch ? e.touches[0] : e,
            matrix, x, y,
            c1, c2;

        if (!that.enabled) return;

        if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);
。。。。。

//觸發onBeforeScrollStart
onBeforeScrollStart: function (e) { e.preventDefault(); },

從代碼中咱們可知 咱們調用new iScroll("scroll-box",{hScrollbar:false,vScrollbar:false,vScroll:false};的時候 首頁會調用get

onBeforeScrollStart : function(){
e.preventDefault();
}

它默認是直接取消默認事件的 
所以須要重寫onBeforeScrollStart事件,判斷touch的滑動距離,只在橫向滑動距離大於豎向滑動距離時(也就是左右滑動時)才取消默認事件,這樣就不影響頁面滾動了

代碼以下:

new iScroll("scroll-box",{hScrollbar:false,vScrollbar:false,vScroll:false, 
onBeforeScrollStart: function ( e ) {
if ( this.absDistX > (this.absDistY + 5 ) ) {
e.preventDefault();
}
}

}

 

到這裏的時候感受就不錯了。可是不要高興的太早。源碼

上下滑動橫向滾動區域,頁面確實能夠滾動了,但在多體驗了幾回頁面以後,又出現了一個問題。it

先左右滑動該區域,滾動中止後再按住該區域想滾動頁面,你會發現它仍是不能滾動頁面,這時你再點擊一次該區域,這時能夠了。這相對於你須要觸摸2次才能滾動頁面, 這樣的行爲仍是讓人沒法接受。io

通過多翻測試,我把問題鎖定到absDistX/Y上。最後發現,在左右滑動以後absDistX/Y的值不會重置,第二次滑動該區域時執行onBeforeScrollStart事件,裏面absDistX/Y值是上一次的值,因此程序仍是阻止了頁面滾動。

代碼以下:

new iScroll("scroll-box",{hScrollbar:false,vScrollbar:false,vScroll:false, 
                            onBeforeScrollStart: function ( e ) {
                                if ( this.absDistX > (this.absDistY + 5 ) ) {
                                    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的值。

這下OK 搞定了! 

相關文章
相關標籤/搜索