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


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

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

思路如下:

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

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

源碼流程:

//事件觸發
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};的時候 首頁會調用

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();
}
}

}

 

到這里的時候感覺就不錯了。但是不要高興的太早。

上下滑動橫向滾動區域,頁面確實可以滾動了,但在多體驗了幾次頁面之后,又出現了一個問題。

先左右滑動該區域,滾動停止后再按住該區域想滾動頁面,你會發現它還是不能滾動頁面,這時你再點擊一次該區域,這時可以了。這相對於你需要觸摸2次才能滾動頁面, 這樣的行為還是讓人無法接受。

經過多翻測試,我把問題鎖定到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 搞定了! 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM