JS 13.4.3 鼠标与滚轮事件

鼠标与滚轮事件

DOM3级中定义了9个鼠标事件;

click,dbclick,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup;

页面上的所有元素都支持鼠标事件;

除了mouseenter和mouseleave,所有鼠标事件都会冒泡,也可以被取消,而取消鼠标事件将会影响浏览器的默认行为;

取消鼠标事件的默认行为还会影响其他事件,因为鼠标事件与其他事件是密不可分的关系;

只有在同一个元素上相继触发mousedown和mouseup事件,才会触发click事件;

如果mousedown或mouseup中的一个被取消,就不会触发click事件;

能力检测;

var isSupported = document.implementation.hasFeature("MouseEvent", "3.0")

mousewheel事件跟踪鼠标滚轮,类似于Mac的触控板;

客户区坐标位置

clientX,clientY;

var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function (event) {
    event = EventUtil.getEvent(event);
    alert("Client coordinates: " + event.clientX + "," + event.clientY);
});

页面坐标位置

pageX,pageY;

屏幕坐标位置

screenX,screenY;

修改键

Shift,Ctrl,Alt和Meta(在Windows 键盘中是Windows键,在苹果机中是Cmd键);

它们经常被用来修改鼠标事件的行为;

var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function (event) {
    event = EventUtil.getEvent(event);
    var keys = new Array();
    if (event.shiftKey) {
        keys.push("shift");
    }
    if (event.ctrlKey) {
        keys.push("ctrl");
    }
    if (event.altKey) {
        keys.push("alt");
    }
    if (event.metaKey) {
        keys.push("meta");
    }
    alert("Keys: " + keys.join(","));
});

相关元素

在发生mouseover和mouserout事件时,还会涉及更多的元素;

这两个事件都会涉及把鼠标指针从一个元素的边界之内移动到另一个元素的边界之内;

对mouseover事件而言,事件的主目标是获得光标的元素,而相关元素就是那个失去光标的元素;

类似地,对mouseout事件而言,事件的主目标是失去光标的元素,而相关元素则是获得光标的元素;

跨浏览器的获取相关元素的方式;

var EventUtil = {
//省略了其他代码
    getRelatedTarget: function (event) {
        if (event.relatedTarget) {
            return event.relatedTarget;
        } else if (event.toElement) {
            return event.toElement;
        } else if (event.fromElement) {
            return event.fromElement;
        } else {
            return null;
        }
    },
//省略了其他代码
};

DOM通过event对象的relatedTarget属性提供了相关元素的信息;

这个属性只对于mouseover和mouseout事件才包含值;对于其他事件,这个属性的值是null;

使用;

var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "mouseout", function (event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var relatedTarget = EventUtil.getRelatedTarget(event);
    alert("Moused out of " + target.tagName + " to " + relatedTarget.tagName);
});

鼠标按钮

对于mousedown和mouseup事件来说,则在其event对象存在一个button属性,表示按下或释放的按钮;

DOM的button属性可能有如下3个值:

0表示主鼠标按钮,1表示中间的鼠标按钮(鼠标滚轮按钮),2表示次鼠标按钮;

在常规的设置中,主鼠标按钮就是鼠标左键,而次鼠标按钮就是鼠标右键;

IE8及之前版本中button属性与DOM的button不同;

于是,兼容IE的getButton();

var EventUtil = {
//省略了其他代码
    getButton: function (event) {
        if (document.implementation.hasFeature("MouseEvents", "2.0")) {
            return event.button;
        } else {
            switch (event.button) {
                case 0:
                case 1:
                case 3:
                case 5:
                case 7:
                    return 0;
                case 2:
                case 6:
                    return 2;
                case 4:
                    return 1;
            }
        }
    },
//省略了其他代码
};

// 使用
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "mousedown", function (event) {
    event = EventUtil.getEvent(event);
    alert(EventUtil.getButton(event));
});

更多的事件信息

“DOM2级事件”规范在event对象中还提供了detail属性,用于给出有关事件的更多信息;

对于鼠标事件来说,detail中包含了一个数值,表示在给定位置上发生了多少次单击;

在同一个元素上相继地发生一次mousedown和一次mouseup事件算作一次单击;

detail属性从1开始计数,每次单击发生后都会递增;

如果鼠标在mousedown和mouseup之间移动了位置,则detail会被重置为0;

IE为鼠标事件提供了更多属性,然而这些属性的用处并不大,

原因一方面是只有IE支持它们,另一方是它们提供的信息要么没有什么价值,要么可以通过其他方式计算得来;

心疼(

鼠标滚轮事件

与mousewheel事件对应的event对象除包含鼠标事件的所有标准信息外,还包含一个特殊的wheelDelta属性;

当用户向前滚动鼠标滚轮时,wheelDelta是120的倍数;

当用户向后滚动鼠标滚轮时,wheelDelta是-120的倍数;

这个事件可以在任何元素上面触发,最终会冒泡到document(IE8)或window(IE9,Opera,Chrome 及Safari)对象;

当然了,Firefox和Opera对此的实现也有差别,于是;

var EventUtil = {
//省略了其他代码
    getWheelDelta: function (event) {
        if (event.wheelDelta) {
            return (client.engine.opera && client.engine.opera < 9.5 ?
                -event.wheelDelta : event.wheelDelta);
        } else {
            return -event.detail * 40;
        }
    },
//省略了其他代码
};

// 使用
(function () {
    function handleMouseWheel(event) {
        event = EventUtil.getEvent(event);
        var delta = EventUtil.getWheelDelta(event);
        alert(delta);
    }

    EventUtil.addHandler(document, "mousewheel", handleMouseWheel);
    EventUtil.addHandler(document, "DOMMouseScroll", handleMouseWheel);
})();

触摸设备

iOS和Android没有鼠标,一些要点;

1.不支持dblclick事件;双击浏览器窗口会放大画面,而且没有办法改变该行为;

2.轻击可单击元素会触发mousemove事件;

如果此操作会导致内容变化,将不再有其他事件发生;

如果屏幕没有因此变化,那么会依次发生mousedown,mouseup和click事件;

轻击不可单击的元素不会触发任何事件;

可单击的元素是指那些单击可产生默认操作的元素(如链接),或者那些已经被指定了onclick事件处理程序的元素;

3.mousemove事件也会触发mouseover和mouseout事件;

4.两个手指放在屏幕上且页面随手指移动而滚动时会触发mousewheel和scroll事件;

无障碍性问题

不建议使用click之外的其他鼠标事件来展示功能或引发代码执行;

因为这样会给盲人或视障用户造成极大不便;

1.使用click事件执行代码;

有人指出通过onmousedown执行代码会让人觉得速度更快;对视力正常的人来说这是没错的;

但是,在屏幕阅读器中,由于无法触发mousedown事件,

结果就会造成代码无法执行;

2,不要使用onmouseover向用户显示新的选项;

原因同上,屏幕阅读器无法触发这个事件;

如果确实非要通过这种方式来显示新选项,可以考虑添加显示相同信息的键盘快捷方式;

3.不要使用dblclick执行重要的操作;键盘无法触发这个事件;