隨手記 - 瘋狂觸發滾輪事件的Mac觸控板

頭幾天官網剛上線,就接到投訴說有問題。過去一看,我靠什麼鬼?!Mac下用觸控板一滑到底,——首頁上用iscroll寫的翻頁效果直接全軍覆沒。javascript

這個bug來的莫名其妙,問了一圈人也沒什麼思路,後來本身上網搜,在一個頁面上找到一段關於Mac的觸控板的手勢滑動會瘋狂觸發滾輪事件的記錄,可是輪到具體的解決方案就語焉不詳了。沒轍,靠天沒用,仍是靠本身吧~java

這裏先簡單介紹下。出問題的首頁用的是iscroll插件,用snap屬性作的整屏翻頁的效果,翻頁用鼠標滾輪驅動,這塊用的是MDN上的一個滾輪事件的兼容代碼,回調使用iscroll的接口完成向上/向下翻頁的效果。git

回到這個問題上。一開始我想用事件防抖解決,因而用setTimeout()本身寫了個:觸發事件後先進入延時,延時後執行函數;若是在延時內仍有事件觸發,則取消原有的延時從新計時。瀏覽器

// 打底用的zepto.js,addWheelListener是滾輪事件的兼容插件,下同~
var wheelTimer = false;
var wheelSlide = function (e) {
    e.preventDefault();
    clearTimeout(timer);
    if (e.deltaY > 0) {
        wheelTimer = setTimeout(function(){
            iScroll.next();
        }, 100);
    } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) {
        wheelTimer = setTimeout(function(){
            iScroll.prev();
        }, 100);
    }
}
addWheelListener($('body')[0], wheelSlide);

我本意是用延時抵消掉重複觸發的滾輪事件,最後合成一個事件觸發,沒想到測試以後,Mac上的問題並無解決。ide

因而我想,用事件防抖的思路處理應該仍是不對,即使是延遲時間較短,若是事件持續觸發的話確定翻頁仍是會被無限的延遲阻塞掉,至此我想換用事件節流再試試。在找資料的時候,意外發現了Underscore.js這個工具庫,裏邊不只有現成的節流和防抖(中文文檔裏用的是「防反跳」)函數能夠用,並且還支持鏈式調用,而且壓縮版本也才十幾k,正合我意。函數

說幹就幹,立刻用Underscore擼了個事件節流版的:工具

var wheelSlide = _(function (e) {
    e.preventDefault();
    if (e.deltaY > 0) {
        iScroll.next();
    } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) {
        iScroll.prev();
    }
}).throttle(400);//這裏毫秒數用了400,大概至關於一個短動畫的執行時間
addWheelListener($('body')[0], wheelSlide);

鏈式寫法看上去還挺不錯的!進本機瀏覽器(PC)……嗯?爲啥最後會跳一下?趕忙翻文檔,又加了個參數上去:測試

var wheelSlide = _(function (e) {
    e.preventDefault();
    if (e.deltaY > 0) {
        iScroll.next();
    } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) {
        iScroll.prev();
    }
}).throttle(400, {trailing: false});
addWheelListener($('body')[0], wheelSlide);

這回PC上卻是正常了,Mac也從一滑到底變成了有「段落感」的跳動,但結果仍是不對……
一狠心把毫秒數改爲了5000,結果呢:還、是、不、對、、、。。。
(//陷入循環懵逼狀態ing……)
痛定思痛,必定是文檔看的不夠多!因而又啃了一遍Underscore.js的文檔(雖然是翻譯的,囧……),發現防抖竟然有個[immediate]參數,是能夠優先執行的!大喜過望~接着擼:動畫

var wheelSlide = _(function (e) {
    e.preventDefault();
    if (e.deltaY > 0) {
        wScroll.next();
    } else if (e.deltaY < 0 && wScroll.currentPage.pageY != 0) {
        wScroll.prev();
    }
}).debounce(600, true);// 原本想改回400的,有點心虛因此又加了200……
addWheelListener($('body')[0], wheelSlide);

竟然PC和Mac都能一頁頁的翻頁了有!沒!有!不過翻頁的動做還有點遲滯,因而果斷把毫秒數改小:400、200、100,……Bingo!插件

最終代碼:

var wheelSlide = _(function (e) {
    e.preventDefault();
    if (e.deltaY > 0) {
        wScroll.next();
    } else if (e.deltaY < 0 && wScroll.currentPage.pageY != 0) {
        wScroll.prev();
    }
}).debounce(50, true);
addWheelListener($('body')[0], wheelSlide);

總結:

  1. Mac觸控板bug踩坑 +1;

  2. 理解了事件節流和事件防抖的概念;

  3. Underscore.js真好用;

  4. 感謝git把每次的修改都記了下來。

相關文章
相關標籤/搜索