跨浏览器鼠标滚轮事件及测试用例

浏览器差异:

  • Firefox的滚轮事件是DOMMouseScroll,其他浏览器使用的是mousewheel
  • Firefox事件的event对象使用detail值表示滚轮方向,负3表示向上(前),正3表示向下(后)。其他浏览器使用wheelDelta值表示滚轮方向,正120表示向上(前),负120表示向下(后)。Opera 11.11即有detail值(同FF)也有wheelDelta值。
  • 不要和正负3或正负120做等值比较来滚轮判断方向,应该和零比较。比如wheelDelta值大于0表示向上(前)。这么做的原因是有些用户的鼠标是基于厂家自己的驱动运行的,有更高级的灵敏度识别,在用户快速滚动滑轮的时候,event对象的detail或wheelDelta会出现其他值得情况。
  • 经典得基本已成为废话,IE678使用attachEvent/detachEvent,其他浏览器使用addEventListener/removeEventListener。

封装后的代码,加入统一的方向标识和一些常用的功能:

  • 为event对象加入wheel值表示滚轮方向,正1表示向上(前),负1表示向下(后)。
  • 为event对象加入wheelDir值表示滚轮方向,up表示向上(前),down表示向下(后)。
  • 纠正了IE678下事件函数内部的this值,指向绑定事件的DOM元素。
  • 为IE678下事件函数传染event对象。
  • 可以通过第三个参数决定是否阻止滚轮的默认行为,即触发整个网页的滚动事件。默认为true,阻止滚轮的默认行为。
  • 同一个DOM元素可以绑定多个滚轮事件但不允许绑定重复的事件。

实现代码:

/*
 * mousewheel.js (c) Doomin|Joy-Studio
 * @example
 *     mouseWheel.on(el, callback)
 *     mouseWheel.on(el, callback, false) do NOT prevent default event
 *     mouseWheel.un(el, callback)
*/
var mouseWheel = (function() {
    var doc = document,
    types = ['DOMMouseScroll', 'mousewheel'],
    fixedEvent = function(e) {
        e.wheel = (e.wheelDelta ? e.wheelDelta: -e.detail) > 0 ? 1 : -1;
        e.wheelDir = e.wheel > 0 ? 'up': 'down';
        return e;
    };

    //return the api method
    return {
        on: function(el, fn, preventDefault) {
            if (typeof preventDefault !== 'boolean') {
                preventDefault = true;
            }

            var fixedFn = function(e) {
                e = fixedEvent(e || window.event);
                if (preventDefault) {
                    if (e.preventDefault) {
                        e.preventDefault()
                    } else {
                        e.returnValue = false;
                    }
                }
                fn.call(el, e);
            },
            wheelHash = el.wheelHash;

            if (!wheelHash) {
                wheelHash = {};
                wheelHash[fn] = fixedFn;
                el.wheelHash = wheelHash;
            } else {
                //ignore the repeat event
                if (wheelHash[fn]) return;
                wheelHash[fn] = fixedFn;
            }

            if (doc.addEventListener) {
                var i = types.length;
                while (i--) {
                    el.addEventListener(types[i], fixedFn, false);
                }
            } else {
                el.attachEvent('onmousewheel', fixedFn);
            }
        },
        un: function(el, fn) {
            if (!el.wheelHash) return;
            var wheelHash = el.wheelHash;
            if (doc.removeEventListener) {
                var i = types.length;
                while (i--) {
                    el.removeEventListener(types[i], wheelHash[fn], false);
                }
            } else {
                el.detachEvent('onmousewheel', wheelHash[fn]);
            }
            delete wheelHash[fn];
        }
    };
})();

如何使用:

//定义滚轮事件
var myWheel = function(e){
    console.log(e.wheelDir);
}
//添加滚轮事件
mouseWheel.on(element, myWheel);
//删除滚轮事件
mouseWheel.un(element, myWheel);

鼠标滚轮事件的几个经典应用:

  • 地图,比如Google Map,百度地图。
  • 表单Spinner控件。
  • 自定义滚动条。
  • 控制字体大小。
  • 其他,有待同学们自己发现,创新和应用。

相关资源:http://www.adomas.org/javascript-mouse-wheel/

测试地址:http://www.joy-studio.com/demo/mousewheel/cross-browser-mousewheel-and-demo.html

原文地址:http://www.joy-studio.com/frontend-develop/cross-browser-mousewheel-and-demo.html

posted @ 2012-07-10 17:34  无赖君子  阅读(980)  评论(0编辑  收藏  举报