随手记 - 疯狂触发滚轮事件的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把每次的修改都记了下来。

相关文章
相关标签/搜索