zoukankan      html  css  js  c++  java
  • javascript滚轮事件总结

    滚轮事件是一个非常有用的事件,在翻页或放大时,通常都用到它。但它在各浏览器中实现兼容是相对比较困难的,号称最标准的FF,用了一个私有实现DOMMouseScroll,而使用mousewheel的其他浏览器或多或少有点bug。我们先看各浏览器对它的支持程度吧。

    IEfirefoxsafarichromeopera
    window对象falsetruetruetruetrue
    文档对象truetruetruetruetrue
    元素节点truetruetruetruetrue

    接着我们看一下,如何在火狐中实现滚轮事件的事件分派:

            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)
    

    我们可以看到虽然其他标准浏览器也支持这个名为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)
    

    这个在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)
        }
    

    说完事件分派,就到事件绑定部分。虽然现在只有FF在用DOMMouseScroll,但考虑到未来FF改用的mousewheel的可能,我们还是写个程序来检测其需要的事件类型吧。最后我们还要在回调函数中修正其滚动属性:

    • IE6-11,chrome的属性名为wheelDelta,ff那边为detail,现在统一为delta。
    • IE6-11等往上滚一圈为120,往下滚一圈为-120。ff那边往上滚一圈为-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)
    });
    

    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);
    
    firefox chrome IE11 safari5.1.7
    wheel
    deltaX 0
    deltaY 3(向下)
    deltaZ 0
                        
    deltaX: -0
    deltaY: 100
    deltaZ: 0
    detail: 0
    wheelDelta: -120
    wheelDeltaX: 0
    wheelDeltaY: -120
                        
    deltaX: 0
    deltaY: 52.5
    deltaZ: 0
    detail: 0
                        
    
                        
    mousewheel
    type竟然是wheel
    deltaX: -0
    deltaY: 100
    deltaZ: 0
    detail: 0
    wheelDelta: -120
    wheelDeltaX: 0
    wheelDeltaY: -120
                        
    wheelDelta:-120
    wheelDelta: -120
    wheelDeltaX: 0
    wheelDeltaY: -120
                        
    DOMMouseScroll detail:3(向下)
  • 相关阅读:
    JDBC的使用流程
    typescript vscode /bin/sh: ts-node: command not found
    小程序打开app场景
    设置获取cookie,setCookie,getCookie
    解决IOS微信页面回退不刷新问题
    百度小程序添加编译
    百度小程序审核不通过,基础库问题
    Charles Mac 破解安装和证书安装成功抓包单个域名是unknown
    xhrFields实现跨域访问
    Mac上启动nginx报错:nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1725462.html
Copyright © 2011-2022 走看看