javascript滾輪事件總結

來源:互聯網
上載者:User

滾輪事件是一個非常有用的事件,在翻頁或放大時,通常都用到它。但它在各瀏覽器中實現相容是相對比較困難的,號稱最標準的FF,用了一個私人實現DOMMouseScroll,而使用mousewheel的其他瀏覽器或多或少有點bug。我們先看各瀏覽器對它的支援程度吧。

IE firefox safari chrome opera
window對象 false true true true true
文檔對象 true true true true true
元素節點 true true true true true

接著我們看一下,如何在Firefox中實現滾輪事件的事件指派:

        window.addEventListener("DOMMouseScroll",function(event){          alert(event.type)          alert(event.clientY)        },false);        var event = document.createEvent("MouseEvent");        //為了證明指派成功,特意將其clientY設為90        event.initMouseEvent("DOMMouseScroll",true, null, window,0,0,0,0,90,false,false,false,false,0,null);        window.dispatchEvent(event)

<br /><!doctype html><br /><html lang="zh-ch"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>mousewheel的事件指派 by 司徒正美</title></p><p> <script type="text/javascript"></p><p> window.onload = function(){</p><p> window.addEventListener("DOMMouseScroll",function(event){<br /> alert(event.type)<br /> alert(event.clientY)<br /> },false);<br /> var event = document.createEvent("MouseEvent");<br /> //為了證明指派成功,特意將其clientY設為90<br /> event.initMouseEvent("DOMMouseScroll",true, null, window,0,0,0,0,90,false,false,false,false,0,null);<br /> window.dispatchEvent(event)</p><p> }</p><p> </script><br /> <style type="text/css"></p><p> </style></p><p> </head><br /> <body><br /> </body><br /></html><br />

運行代碼

我們可以看到雖然其他標準瀏覽器也支援這個名為DOMMouseScroll的事件發派,但當我們手動滾動滑鼠滑輪時,也只有FF有反應,彈出兩個alert。對於其他標準瀏覽器,我們改用mousewheel試試。

        window.addEventListener("mousewheel",function(event){          alert(event.type)          alert(event.clientX)        },false);        var event = document.createEvent("MouseEvent");        //為了證明指派成功,特意將其clientX設為120        event.initMouseEvent("mousewheel",true, null, window,0,0,0,120,0,false,false,false,false,0,null);        window.dispatchEvent(event)

<br /><!doctype html><br /><html lang="zh-ch"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>mousewheel的事件指派 by 司徒正美</title></p><p> <script type="text/javascript"><br /> window.addEventListener("mousewheel",function(event){<br /> alert(event.type)<br /> alert(event.clientX)<br /> },false);<br /> var event = document.createEvent("MouseEvent");<br /> //為了證明指派成功,特意將其clientX設為120<br /> event.initMouseEvent("mousewheel",true, null, window,0,0,0,120,0,false,false,false,false,0,null);<br /> window.dispatchEvent(event)</p><p> </script><br /> <style type="text/css"></p><p> </style></p><p> </head><br /> <body><br /> </body><br /></html><br />

運行代碼

這個在FF的以外的標準瀏覽器見效,FF只能實現事件指派,不能實現手動觸發。可以說,如果非原瀏覽器原生支援的事件類型,addEventListener是一概不理會的。

對於IE就簡單得多了,它沒有初始化事件的步驟,你也無法設定其屬性,因為那是唯讀,但可以設定自訂屬性。

      window.onload = function(){        document.attachEvent("onmousewheel",function(){          var e = window.event;          alert(e)          alert(e.type)          alert(e.aa)        });      var event = document.createEventObject();      event.aa = "司徒正美"      document.fireEvent("onmousewheel",event)    }

<br /><!doctype html><br /><html lang="zh-ch"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>mousewheel的事件指派 by 司徒正美</title></p><p> <script type="text/javascript"><br /> window.onload = function(){<br /> document.attachEvent("onmousewheel",function(){<br /> var e = window.event;<br /> alert(e)<br /> alert(e.type)<br /> alert(e.aa)<br /> });<br /> var event = document.createEventObject();<br /> event.aa = "司徒正美"</p><p> document.fireEvent("onmousewheel",event)<br /> }<br /> </script><br /> <style type="text/css"></p><p> </style></p><p> </head><br /> <body><br /> </body><br /></html><br />

運行代碼

說完事件指派,就到事件綁定部分。雖然現在只有FF在用DOMMouseScroll,但考慮到未來FF改用的mousewheel的可能,我們還是寫個程式來檢測其需要的事件類型吧。最後我們還要在回呼函數中修正其滾動屬性:

  • IE的屬性名稱為detail,w3c那邊為wheelDelta,現在統一為delta。
  • IE等往上滾一圈為120,往下滾一圈為-120。w3c那邊往上滾一圈為-3,往下滾一圈為3,但opera9x系列卻實現錯誤,與IE滾動方向一致,不過10後又修複。
  • safari早期版本,wheelDelta會出現浮點數的情況,我們需要自行取整。
              function addEvent(el, type, callback, useCapture  ){                    if(el.dispatchEvent){//w3c方式優先                        el.addEventListener( type, callback, !!useCapture  );                    }else {                        el.attachEvent( "on"+type, callback );                    }                    return callback;//返回callback方便卸載時用                }                var wheel = function(obj,callback){                    var wheelType = "mousewheel"                    try{                        document.createEvent("MouseScrollEvents")                        wheelType = "DOMMouseScroll"                    }catch(e){}                    addEvent(obj, wheelType,function(event){                        if ("wheelDelta" in event){//統一為±120,其中正數表示為向上滾動,負數表示向下滾動                            var delta = event.wheelDelta                            //opera 9x系列的滾動方向與IE保持一致,10後修正                            if( window.opera && opera.version() < 10 )                                delta = -delta;                            //由於事件對象的原有屬性是唯讀,我們只能通過添加一個私人屬性delta來解決相容問題                            event.delta = Math.round(delta) /120; //修正safari的浮點 bug                        }else if( "detail" in event ){                            event.wheelDelta = -event.detail * 40//為FF添加更福士化的wheelDelta                            event.delta = event.wheelDelta /120  //添加私人的delta                        }                        callback.call(obj,event);//修正IE的this指向                    });                }

用法:

wheel(document,function(e){  alert(e.delta)});

</p><p><!DOCTYPE HTML><br /><html><br /> <head><br /> <title>滾輪事件mousewheel by 司徒正美</title><br /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><br /> <style><br /> body{<br /> padding:10px 100px;<br /> }<br /> .slider{<br /> width:48px;<br /> height:200px;<br /> padding: 5px 0px;<br /> background:#eee;<br /> cursor:n-resize;<br /> }<br /> .slider-slot {<br /> width:16px;<br /> margin:10px 15px;<br /> height:180px;<br /> background:#eee;<br /> border:1px solid gray;<br /> border-color:#999 white white #999;<br /> position:relative;<br /> }<br /> .slider-trigger {<br /> width:14px;<br /> height:18px;<br /> font:1px/0 arial;<br /> border:1px solid gray;<br /> border-color:white #999 #999 white;<br /> background:#ccc;<br /> position:absolute;<br /> }</p><p> </style><br /> <script type="text/javascript">// <![CDATA[<br /> window.onload = function(){<br /> function log(s){<br /> window.console && console.log(s);<br /> }<br /> var get = function(i) {<br /> return document.getElementById( i );<br /> }<br /> function addEvent(el, type, callback, useCapture ){<br /> if(el.dispatchEvent){//w3c方式優先<br /> el.addEventListener( type, callback, !!useCapture );<br /> }else {<br /> el.attachEvent( "on"+type, callback );<br /> }<br /> return callback;//返回callback方便卸載時用<br /> }<br /> var wheel = function(obj,callback){<br /> var wheelType = "mousewheel"<br /> try{<br /> document.createEvent("MouseScrollEvents")<br /> wheelType = "DOMMouseScroll"<br /> }catch(e){}<br /> addEvent(obj, wheelType,function(event){<br /> if ("wheelDelta" in event){//統一為±120,其中正數表示為向上滾動,負數表示向下滾動<br /> var delta = event.wheelDelta<br /> //opera 9x系列的滾動方向與IE保持一致,10後修正<br /> if( window.opera && opera.version() < 10 )<br /> delta = -delta;<br /> //由於事件對象的原有屬性是唯讀,我們只能通過添加一個私人屬性delta來解決相容問題<br /> event.delta = Math.round(delta) /120; //修正safari的浮點 bug<br /> }else if( "detail" in event ){<br /> event.wheelDelta = -event.detail * 40//為FF添加更福士化的wheelDelta<br /> event.delta = event.wheelDelta /120 //添加私人的delta<br /> }<br /> callback.call(obj,event);//修正IE的this指向<br /> });<br /> }<br /> function preventDefault(e){<br /> if( e.preventDefault )<br /> e.preventDefault();<br /> e.returnValue = false;<br /> }</p><p> wheel(get("number"), function(e){<br /> this.value = (Number(this.value) || 0) + e.delta //120 ;<br /> this.select();<br /> preventDefault(e)<br /> })</p><p> wheel(get("img"), function(e){<br /> this.style.width = this.offsetWidth + e.delta + 'px';<br /> this.style.height = this.offsetHeight + e.delta + 'px';<br /> preventDefault(e)</p><p> })</p><p> function range( num, max,min ) {<br /> return Math.min( max, Math.max( num,min ) );<br /> }<br /> var tar = get('sliderTrigger');<br /> wheel(get("slider"), function(e){<br /> preventDefault(e)<br /> tar.style.top = range( tar.offsetTop + ( -1 * e.delta * 10 ),160,0 ) + 'px';<br /> })<br /> }<br /> </script><br /> </head><br /> <body><br /> <h2>文字框增加/減少值</h2><br /> <div><input type="text" value="300" id="number"><br /> <span>文字框獲得焦點後滾動滑鼠滾輪</span><br /> </div><br /> <h2>滑鼠滾動縮放圖片</h2><br /> <div><br /> <img id="img" style="cursor:-moz-zoom-in" title="滑鼠滾動 縮放大小" src="http://www.baidu.com/img/baidu.gif" /><br /> </div><br /> <h2>滑鼠滾動控制滑塊移動</h2><br /> <div id="slider" class="slider"><br /> <div class="slider-slot"><br /> <div id="sliderTrigger" class="slider-trigger"><br /> <strong> </strong><br /> <strong> </strong><br /> <strong> </strong><br /> <strong></strong><br /> <strong></strong><br /> </div><br /> </div><br /> </div></p><p> </body><br /></html></p><p>

運行代碼

Event property Applies to event: Up 1 click Up 2 clicks Down 1 click Down 2 clicks
e.wheelDelta

Supported in Non
FF browsers

onmousewheel and in non FF
browsers
120 240 -120 -240
e.detail

Supported in FF and
Opera

DOMMouseScroll and in FF
(as of FF3.x)
-1 -2 1 2

在FF官網還給出一個相容方案:

// 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    if ( document.onmousewheel !== undefined ) {        // Webkit and IE support at least "mousewheel"        support = "mousewheel"    }    try {        // Modern browsers support "wheel"        WheelEvent("wheel");        support = "wheel";    } catch (e) {}    if ( !support ) {        // let's assume that remaining browsers are older Firefox        support = "DOMMouseScroll";    }     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);
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.