Rumah  >  Artikel  >  hujung hadapan web  >  了解JS滚轮事件(mousewheel/DOMMouseScroll)

了解JS滚轮事件(mousewheel/DOMMouseScroll)

coldplay.xixi
coldplay.xixike hadapan
2020-06-13 17:48:424432semak imbas

了解JS滚轮事件(mousewheel/DOMMouseScroll)

JS滚轮事件(mousewheel/DOMMouseScroll)了解

一、学无止境、温故知新

//zxx: 本段与技术无关,一些很个人的吐槽,可以跳过
已经没有了小学生时代过目不忘的记忆力了,很多自己折腾的东西、接触的东西,短短1年之后就全然不记得了。比方说,完全记不得获取元素与页面距离的方法(getBoundingClientRect),或者是不记得现代浏览器下触发DOM自定义事件的方法(dispatchEvent). 显然,适当的温习,翻阅以前的东西,或者自己空余时间处理相关的东西还是有必要的。其实,细想,东西记不住是自己自身原因,在折腾的时候就没有想方设法牢记(而不是通过反复使用记住)。比方说getBoundingClientRect就是“得到客户端矩形边界”的意思,或者使用邪恶记法记住“割(g)逼(b)艹(c)软(r)”。dispatchEvent方法使用“3步走”,“创建(createEvent)-初始(init*Event)-分派(dispatchEvent)”。

学习的脚步不能停止。一站到底的那些“变态”们也有不知道的东西,显然,我们这些草辈,尤其年轻的自己,不知道的更多。谁年轻的时候没有过或多或少 的迷茫,问自己“路在何方”,问自己“该做哪个方向”,无论你选择的是什么,学习的脚步是不能停止的。坚持着坚持着,路自然就会清晰,你就会知道接下来该 怎么走了。只怕畏首畏尾,得过且过,年轻就是资本,义无反顾前行吧。

我凭着兴趣走上现在的道路,完全是兴趣学习(我喜欢这些,我要学),不是职业学习(做前端需要什么,我就去学什么)。工作的这些年,技术、产品的自 我沉浸不知不觉限制了自己的眼界,好在意识到问题的存在其实已经解决了问题的一半。这里之所以会说这些是想提醒自己,万万不可矫枉过正,技术、产品的学习 还是主要的,只是要多多抬头看看办公室之外的世界(不是刷微博获得的浅认识)。

昨天机缘巧合遇到“滚轮事件”,以前折腾“自定义滚动条”时候使用过鼠标滚轮事件,不过这是基于MooTools已经兼容好的mousewheel事件实现的,如果要说出其中的实现机制,浏览器兼容差异等,就傻眼了。学无止境,因此,查阅之,实践之,整理之。

二、兼容差异大全

滚轮事件的兼容性差异有些不拘一格,不是以往的IE8-派和其他派,而是FireFox派和其他派。

包括IE6在内的浏览器是使用onmousewheel,而FireFox浏览器一个人使用DOMMouseScroll. 经自己测试,即使现在FireFox 19下,也是不识onmousewheel。

一个最简单的使用差异(body滚动条由内部一定高div撑开):

document.body.onmousewheel = function(event) {
    event = event || window.event;
    console.dir(event);
};

document.body.addEventListener("DOMMouseScroll", function(event) {
    console.dir(event);
});

以上输出差异见下面(IE7, IE10, Chrome, 以及FireFox,鼠标向下滚动, win7)(可点击此页面单独查看表格内容):

三、兼容的滚轮事件方法

知己知彼百战百胜,知道了差异就知道如何处理这些差异。毕竟不是写JS库,我们这里只处理滚动方向这块的差异。

整合我们通常事件添加方法,于是有(下代码代号为addEvent.js):

/**
 * 简易的事件添加方法
 */
 define(function(require, exports, module) {
    exports.addEvent = (function(window, undefined) {        
        var _eventCompat = function(event) {
            var type = event.type;            if (type == 'DOMMouseScroll' || type == 'mousewheel') {
                event.delta = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
            }
            //alert(event.delta);
            if (event.srcElement && !event.target) {
                event.target = event.srcElement;    
            }
            if (!event.preventDefault && event.returnValue !== undefined) {
                event.preventDefault = function() {
                    event.returnValue = false;
                };
            }            /* 
               ......其他一些兼容性处理 */
            return event;
        };
        if (window.addEventListener) {
            return function(el, type, fn, capture) {                if (type === "mousewheel" && document.mozHidden !== undefined) {
                    type = "DOMMouseScroll";
                }
                el.addEventListener(type, function(event) {
                    fn.call(this, _eventCompat(event));
                }, capture || false);
            }
        } else if (window.attachEvent) {
            return function(el, type, fn, capture) {
                el.attachEvent("on" + type, function(event) {
                    event = event || window.event;
                    fn.call(el, _eventCompat(event));    
                });
            }
        }
        return function() {};    
    })(window);        
});

于是,我们就可以很从容使用mousewheel事件了。例如:

addEvent(dom, "mousewheel", function(event) {
    if (event.delta < 0) { alert("鼠标向上滚了!"); }
});

相关代码实现如下,下面这个展示的就是平滑移动的核心代码们(代号为slide.js):

/**
 * 简易的列表左右滑动切换效果
 * 鼠标事件是关键,因此,一些数值写死在方法中,纯测试用
 */
 define(function(require, exports, module) {    var Event = require("/study/201304/addEvent.js");
    var _move = function(ele, to, from) {        // 动画实现
        // ...
    };
    return {
        index: 0,
        visible: 4,
        init: function(box) {            // box指滚动的列表容器
            var self = this
              , length = box.getElementsByTagName("li").length;            Event.addEvent(box.parentNode, "mousewheel", function(event) {
                 if (event.delta > 0 && self.index > 0) {                    // 往上滚
                    self.index--;
                 } else if (event.delta < 0 && self.index < length - self.visible) {                     // 往下
                     self.index++;                     
                 } else {
                    return; 
                 }
                 _move(box, -1 * self.index * 140);    
              
                 event.preventDefault();
            });
        }
    };
});

原理很简单,滚轮改变,索引改变,也就是列表的最终位置改变,动画到目标位置即可。

然后,demo页面使用seajs简单调用就可以了!

var $ = function(id) {
    return document.getElementById(id);
};
seajs.use("/study/201304/slide.js", function(slide) {
    slide.init($("slideBox"));
});

就结束了,一些具体细节,例如关于HTML部分,或者动画的实现等,可以去demo等查看代码展示。

不过从效果来看,IE6以及IE7浏览器下的滚动并没有hold页面的滚动条,多番其他尝试也是如此,希望可以有相关经验的同行指点下,优化IE7/IE7浏览器下的体验效果。

原本还想再添加一个自定义滚动条的demo的,一看时间,我勒个去,已经1:11:11了,好不吉利的数字啊,看了下程序员运势万年历,今天不适宜写demo。于是,结语睡觉。

推荐教程:《JS基础教程

Atas ialah kandungan terperinci 了解JS滚轮事件(mousewheel/DOMMouseScroll). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:liqingbo.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam