鼠标 与 滚轮事件
DOM3级中定义了9个鼠标事件,简介如下
<body style="height:1500px;">
<div style="width:200px;height: 200px; border:1px solid red" id="outer">
<div style="width:100px; height: 100px; border:1px solid green" id="inner">
</div>
</div>
</body>
不支持事件冒泡
mouseenter
鼠标从一个元素首次移动该元素范围时触发,该事件不冒泡,而且光标移动到后代元素上不会触发。
mouseleave
鼠标从该元素离开时,触发该事件,该事件不冒泡,而且光标移动到后代元素上不会触发。
这里说个题外话: jquery 的 hover 方法也是根据这两个事件来实现的,大家有时间可以看看
jQuery.fn.extend({
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
},
bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
return this.off( types, null, fn );
},
delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
// ( namespace ) or ( selector, types [, fn] )
return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
}
});
支持事件冒泡:
mousemove
当鼠标指针在元素内部移动时重复地触发(包括后代上),不能通过键盘触发这个事件。
click
在用户单击主鼠标按钮或者按下回车键时触发。
dbclick
用户双击主鼠标键时触发
mouseout
在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发。 不能通过键盘触发这个事件。
mouseover
在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内时触发。不可通过键盘触发这个事件。
mousedown
当鼠标按下时触发该事件,不可通过键盘触发 支持
mouseup
当用户释放鼠标按钮时触发。 不能通过键盘触发这个事件。
除了mouserenter 与 mouseleave ,所有鼠标事件都会冒泡,也可以被取消,而取消鼠标事件将会影响浏览器默认行为。只有在同一个元素上相继触发mousedown 和 mouseup 事件,才会触发click事件;
如果有一个被取消,就不会触发click事件。 只有触发两次click 事件才会触发一次dbclick事件。
这四类事件的触发顺序: IE9+ 其他浏览器
(1) mousedown
(2) mouseup
(3) click
(4) mousedown
(5) mouseup
(6) click
(7) dblclick
在IE8实现中出现了一个bug,因此在双击事件中,会跳过第二个mousedown 和 click 事件,其顺序如下:
(1) mousedown
(2) mouseup
(3) click
(5) mouseup
(7) dblclick
滚轮事件
鼠标事件中还有一类事件。 mousewheel事件。这个事件跟踪鼠标滚轮
鼠标事件的用途:
1 客户区鼠标坐标位置 所有浏览器都支持
clientY \ clientX
这两个表示在与视口 垂直 和 水平的距离,不包括滚动条高度
1 var div = document.getElementById("div"); 2 div.addEventListener("click",function(event){ 3 console.log(event.clientY); 4 console.log(event.clientX); 5 },false);
2 页面区鼠标的位置 IE9+ 其他浏览器
pageY \ pageX
1 var div = document.getElementById("div"); 2 div.addEventListener("click",function(event){ 3 console.log(event.pageY); 4 console.log(event.pageX); 5 },false);
这种情况注意在IE8以及更早版本中不支持event对象包含页面位置属性,不过可以通过滚动信息和 客户区坐标计算出来。
这里可以利用到 document.body (混杂模式)、 document.documentElement(标准模式) 中的 scrollTop 与 scrollLeft
1 var div = document.getElementById("left"); 2 div.attachEvent("onclick",function(event){ 3 var pageX = event.pageX; 4 var pageY = event.pageY; 5 if(pageX === undefined){ 6 pageX = event.clientX + (document.body.scrollLeft|| document.documentElement.scrollLeft) 7 } 8 if(pageY === undefined){ 9 pageY = event.clientY + (document.body.scrollTop|| document.documentElement.scrollTop); 10 } 11 console.log(pageY); 12 })
3 屏幕坐标位置
鼠标除了相对浏览器窗口的位置,还有一个相对于整个电脑屏幕的位置。而通过 screenX 和 screenY属性就可以确定鼠标事件发生时,鼠标指针相对于整个屏幕的坐标信息。
4 修改键
见名思意,通过某些外在操作(键盘 Shift、Ctrl、Alt、Meta(Window中是 Windows键 ,在苹果机中是Cmd键))修改鼠标事件的行为。 DOM为此规定了4个属性,表示这些修改键的状态:shiftKey、ctrlKey、altKey、metaKey。
这些属性中包含都是布尔值,如果相应的键被按下了则为true,否则为false。
1 var div = document.getElementById("left"); 2 div.addEventListener("click",function(event){ 3 var keys = new Array(); 4 event = event; 5 if(event.shiftKey){ 6 keys.push("shift"); 7 } 8 if(event.ctrlKey) { 9 keys.push("Ctrl"); 10 } 11 if(event.altKey){ 12 keys.push("Alt"); 13 } 14 if(event.metaKey){ 15 keys.push("Meta"); 16 } 17 alert("keys:"+keys.join(",")) 18 },false);
IE9+ Firefox Safari Chrome Opera 支持这4个键。IE8及之前版本不支持metaKey属性。
5 相关元素
说到想关元素,就要联想到 如下的两个事件,也只有在这两个事件上才存在相关元素。
主要与 mouseover 和 mouserout 事件时,还会涉及更多的元素。这两个事件涉及把鼠标从一个元素边界内移动到另一个元素的边界之内。
那怎么来获取这个值尼?
在IE9+ 以及其他浏览器中, DOM通过event 对象的 relatedTarget 属性提供了相关元素的信息。这个属性只对与mouseover和 mouseout 事件才包含值。对于其他事件都为空。
在IE8以及之前版本对于获取相关元素提供了 当为mouseover时: formElement属性 ; 当为 mouseout时:toElement属性
可以把下面这个跨浏览器取得相关元素的方法添加到 EventUtil对象中。
1 var EventUtil ={ 2 3 //省略其他代码 4 getRelatedTarget:function(event){ 5 if(event.relatedTarget){ 6 return event.relatedTarget; 7 }else if(event.toElement){ 8 return event.toElement; 9 }else if(event.fromElement){ 10 return event.fromElement; 11 }else{ 12 return null; 13 } 14 } 15 }
下面来看看一个实例:
1 var div = document.getElementById("left"); 2 EventUtil.addHandler(div,"mouseout",function(event){ 3 event = EventUtil.getEvent(event); 4 var target = EventUtil.getTarget(event); 5 var relatedTarget = EventUtil.getRelatedTarget(event); 6 alert(" 鼠标离开从 "+target.tagName +" to "+ relatedTarget.tagName); 7 });
当鼠标离开目标对象(div.left)时,显示对应内容:div to body
6 鼠标按钮
主要针对mousedown 和 mouseup事件来说,则在其event对象中存在一个button属性,表示按下或释放的按钮。 DOM的button属性可能有如下3个值 IE9+ 及其它浏览器。
0:代表主按钮(鼠标左键)
1:代表中间按钮(滚轮)
2:代表次按钮(鼠标右键)
IE8以及之下的版本中,也提供了button属性,但是这个button属性和DOM的button属性有很大差异。
0 :代表没有按下
1 :主
2 :次
3 : 主 + 次
4 : 中
5 : 主 + 中
6 : 次 + 中
7 : 主 + 次 +中
那我们来做下面的处理,把IE 模型规化为DOM方式。毕竟除了IE8及其更早版本之外的浏览器都原生支持DOM模型。
1 getButton:function(event){ 2 if(document.implementation.hasFeature("MouseEvents","2.0")){ 3 return event.button; 4 }else{ 5 switch (event.button){ 6 case 0: 7 case 1: 8 case 3: 9 case 5: 10 case 7: 11 return 0; 12 case 2: 13 case 6: 14 return 2; 15 case 4: 16 return 1; 17 } 18 } 19 }
通过检测 "MouseEvents"这个特性,就可以确定event对象中存在的button属性中是否包含正确的值。如果测试失败,说明是IE,就必须对相应的值进行规范化。
1 var div = document.getElementById("left"); 2 EventUtil.addHandler(div,"mouseout",function(event){ 3 event = EventUtil.getEvent(event); 4 alert(EventUtil.getButton(event)); 5 });