Bobscript

JS控制滚轮横向滚动页面

JS控制滚轮横向滚动页面

本文的目的:

有时候遇到一个很宽的页面,想要用滚轮横向滚动,这时候一般的鼠标估计都不能做到吧?

演示

说得有点抽象,Demo请点击:JS控制滚轮横向滚动演示

鼠标滚轮事件介绍

鼠标滚轮事件一直以来没有统一的事件。太混乱了,各种浏览器甚至操作系统都会产生差异。

简单点来看,分成两个时间段。

最初的时候,所有的浏览器,除了FireFox,都支持一个叫做MouseWheelEvent的事件,甚至IE6都支持哦

addEventListener使用mousewheel即可,attachEvent则是onmousewheel

对于FireFox有一个类似的DOMMouseScroll事件,addEventListener的时候监听addEventListener

然后,到了后来,其实也就是现在,有了一个新的、标准的滚轮事件,就叫WheelEvent了。

得到了下列浏览器的支持:

Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
31 17.0 (17.0) 9.0 Not supported Not supported

不过MDN说

This is really different event object from MouseWheelEvent.

具体怎么不一样,没有说,不过我不在意,不过估计主要是Delta增量的不一样。

不同浏览器不同操作系统下wheelDelta, wheelDeltaX and wheelDeltaY value的差异:MDN原文(En)

对我来说,Delta量多少都无所谓,我只需要得到正向还是反向滚轮就好了,正负判断即可,一次滚轮事件触发一次想要的效果。

来自于MDN的跨浏览器解决方案,它标准化了DeltaY和DeltaX:

// creates a global "addWheelListener" method // example: addWheelListener( elem, function( e ) { console.log( e.deltaY ); e.preventDefault(); } ); (function(window,document) {

    var prefix = "", _addEventListener, onwheel, support;

    // detect event model
    if ( window.addEventListener ) {
        _addEventListener = "addEventListener";
    } else {
        _addEventListener = "attachEvent";
        prefix = "on";
    }

    // detect available wheel event
    support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
                document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
                "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

    window.addWheelListener = function( elem, callback, useCapture ) {
        _addWheelListener( elem, support, callback, useCapture );

        // handle MozMousePixelScroll in older Firefox
        if( support == "DOMMouseScroll" ) {
            _addWheelListener( elem, "MozMousePixelScroll", callback, useCapture );
        }
    };

    function _addWheelListener( elem, eventName, callback, useCapture ) {
        elem[ _addEventListener ]( prefix + eventName, support == "wheel" ? callback : function( originalEvent ) {
            !originalEvent && ( originalEvent = window.event );

            // create a normalized event object
            var event = {
                // keep a ref to the original event object
                originalEvent: originalEvent,
                target: originalEvent.target || originalEvent.srcElement,
                type: "wheel",
                deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
                deltaX: 0,
                delatZ: 0,
                preventDefault: function() {
                    originalEvent.preventDefault ?
                        originalEvent.preventDefault() :
                        originalEvent.returnValue = false;
                }
            };
            
            // calculate deltaY (and deltaX) according to the event
            if ( support == "mousewheel" ) {
                event.deltaY = - 1/40 * originalEvent.wheelDelta;
                // Webkit also support wheelDeltaX
                originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
            } else {
                event.deltaY = originalEvent.detail;
            }

            // it's time to fire the callback
            return callback( event );

        }, useCapture || false );
    }

})(window,document);

除此之外,还会有jQuery的插件,可以像其它的普通事件一样使用,同样也标准化了deltaXdeltaY

// using on
$('#my_elem').on('mousewheel', function(event) {
    console.log(event.deltaX, event.deltaY, event.deltaFactor);
});

// using the event helper
$('#my_elem').mousewheel(function(event) {
    console.log(event.deltaX, event.deltaY, event.deltaFactor);
});

插件地址:jQuery Mousewheel

个人倾向于使用插件,因为它考虑的情况更多一些,可能不同的操作系统下的都考虑好了,而且还有好心人维护。

不过可能不是每个人都需要用到那么多的功能,下面有一个简化版的鼠标滚轮事件,使用的是比较老的方法,没有使用最新的wheel事件,不过就目前来说适用。例子是在图像上滚滚轮缩放图像:

点击查看:滚轮缩放演示地址

点击查看原文

HTML:

<img id="myimage" src="myimage.jpg" alt="my image" />

事件绑定:

var myimage = document.getElementById("myimage");
if (myimage.addEventListener) {
    // IE9, Chrome, Safari, Opera
    myimage.addEventListener("mousewheel", MouseWheelHandler, false);
    // Firefox
    myimage.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else myimage.attachEvent("onmousewheel", MouseWheelHandler);

事件跨浏览器读取:

function MouseWheelHandler(e) {
    // cross-browser wheel delta
    var e = window.event || e; // old IE support
    var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); //判断滚轮方向
    myimage.style.width = Math.max(50, Math.min(800, myimage.width + (30 * delta))) + "px";
    return false;
}

参考资料:

https://developer.mozilla.org/en/docs/DOM/DOM_event_reference/mousewheel

https://developer.mozilla.org/en-US/docs/Web/API/MouseWheelEvent

https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent

https://developer.mozilla.org/en-US/docs/DOM/DOM_event_reference/DOMMouseScroll

http://www.sitepoint.com/html5-javascript-mouse-wheel/