标签:
鼠标与滚轮事件
鼠标事件
“DOM3级事件”中定义了9个鼠标事件。
click:在单击主鼠标按钮(一般是左键)或者按下回车时触发;这意味着onclick事件处理程序既可以通过鼠标也可以通过键盘执行。
dbclick:双击主鼠标按钮(一般是左键)或者按下回车键时触发。
mousedown:按下任意鼠标按钮时触发;不能通过键盘触发。
mouseup:释放鼠标按钮时触发;不能通过键盘触发。
mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发;这个事件不冒泡,而且光标移动到元素的后代元素上不会触发;IE、Firefox9+和Opera支持这个事件。
mouseleave:在鼠标光标从元素上方移动到元素范围之外时触发;这个事件不冒泡,而且光标移动到元素的后代元素上不会触发;IE、Firefox9+和Opera支持这个事件。
mousemove:在鼠标光标在元素内部移动时重复地触发;不能通过键盘触发。
mouseout:在鼠标位于一个元素上方,然后移动到另一个元素时触发,另一个元素可以是这个元素的子元素;不能通过键盘触发。
mouseover:在鼠标位于一个元素外部,然后将其首次移动到另一个元素边界之内时触发;不能通过键盘触发。
只有在同一个元素上相继触发mousedown和mouseup,才会触发click事件;类似地,只有在同一个元素上触发两次click事件,才会触发一次dbclick事件。
这四个事件的触发顺序如下:
(1)mousedown
(2)mouseup
(3)click
(4)mousedown
(5)mouseup
(6)click
(7)dbclick
除了mouseenter、mouseleave、dbclick是“DOM3级事件”新增之外,其它事件都是“DOM2级事件”中定义的。
可以使用如下代码检测浏览器是否支持“DOM2级”鼠标事件:
1 var isSupported = document.implementation.hasFeature("MouseEvents", "2.0"); 2 alert(isSupported); //true
或者是否支持“DOM3级”鼠标事件:
1 var isSupported = document.implementation.hasFeature("MouseEvent", "3.0"); 2 alert(isSupported); //true
注意:“DOM3级”鼠标事件的feature名为MouseEvent;而“DOM2级”为MouseEvents。
客户区坐标位置
通过事件对象event的clientX和clientY属性,可以访问事件发生时鼠标指针在视窗中的水平和垂直坐标。
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 alert("鼠标指针客户区坐标为:水平距离—" + event.clientX + ";" + "垂直距离—" + event.clientY + ""); 4 });
页面坐标位置
通过事件对象event的pageX和pageY属性,可以访问事件发生时鼠标指针在页面中的水平和垂直坐标。
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 alert("鼠标指针页面坐标为:水平距离—" + event.pageX + ";" + "垂直距离—" + event.pageY); 4 });
在页面没有滚动的情况下,pageX和pageY的值与clientX和clientY的值相等。
IE8中的页面坐标位置
IE8及更早版本不支持事件对象上的页面坐标,不过可以使用客户区坐标和滚动信息计算出来。
需要用到document.body(混杂模式)或者document.documentElement(标准模式)中的scrollLeft和scrollTop属性。
计算过程如下:
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 var pageX = event.pageX; 4 var pageY = event.pageY; 5 if(pageX === undefined) { 6 pageX = event.clientX + (document.body.scrollLeft || document.documentElememt.scrollLeft); 7 }; 8 if(pageY === undefined) { 9 pageY = event.clientY + (document.body.scrollTop || document.documentElememt.scrollTop); 10 }; 11 alert("鼠标指针页面坐标为:水平距离—" + pageX + ";" + "垂直距离—" + pageY); 12 });
屏幕坐标位置
通过事件对象event的screenX和screenY属性,可以访问事件发生时鼠标指针在屏幕中的水平和垂直坐标。
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 alert("鼠标指针屏幕坐标为:水平距离—" + event.screenX + ";" + "垂直距离—" + event.screenY); 4 });
修改键
Shift、Ctrl、Alt、Meta(或Windows或Cmd),它们经常被用来修改鼠标事件的行为。
DOM为此规定了4个属性:shiftKey、ctrlKey、altKey、metaKey,表示这些修改键的状态。
这些属性中包含的都是布尔值,如果值为true,表示相应的键被按下。
当某个鼠标事件发生时,通过检测这4个属性,就能确定用户是否按下某个修改键。
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 var keys = new Array(); 4 if(event.shiftKey) { 5 keys.push("shift"); 6 }; 7 if(event.ctrlKey) { 8 keys.push("ctrl"); 9 }; 10 if(event.altKey) { 11 keys.push("alt"); 12 }; 13 if(event.metaKey) { 14 keys.push("meta"); 15 }; 16 alert("点击鼠标的同时按下了:" + keys.join(",")); 17 });
点击鼠标的同时按下Windows键,检测不出来,为何?
IE9、Firefox、Safari、Chrome和Opera都支持这4个属性;IE8及更早版本不支持metaKey属性。
相关元素
对mouseover事件而言,事件的主目标就是获得光标的元素,而相关元素就是失去光标的那个元素;
对mouseout事件而言,事件的主目标就是失去光标的元素,而相关元素就是获得光标的那个元素。
DOM通过event事件对象的relatedTarget属性提供了相关元素的信息。
这个属性只对mouseover和mouseout事件才包含值;对于其他事件,其值为null。
IE8及之前版本不支持relatedTarget属性,但提供相似的属性。
在mouseover事件触发时,IE的fromElement属性中保存着相关元素;在mouseout事件触发时,IE的toElement属性中保存了相关元素。
IE9支持所有的这些属性。
将getRelatedTarge()方法添加到event_util对象中。
1 getRelatedTarget: function(event) { 2 if(event.relatedTarget) { 3 return event.relatedTarget; 4 } else if(event.fromElement) { 5 return event.fromElement; 6 } else if(event.toElement) { 7 return event.toElement; 8 } else { 9 return null; 10 } 11 }
附上完整的event_util对象的代码:
1 var event_util = { 2 //添加事件 3 addHandler: function(element, type, handler) { 4 if(element.addEventListener) { 5 element.addEventListener(type, handler, false); 6 } else if(element.attachEvent) { 7 element.attachEvent("on" + type, handler); 8 } else { 9 element["on" + type] = handler; 10 } 11 }, 12 //移除事件 13 removeHandler: function(element, type, handler) { 14 if(element.removeEventListener) { 15 element.removeEventListener(type, handler, false); 16 } else if(element.detachEvent) { 17 element.detachEvent("on" + type, handler); 18 } else { 19 element["on" + type] = null; 20 } 21 }, 22 //获取事件对象 23 getEvent: function(event) { 24 return event ? event : window.event; 25 }, 26 //获取事件目标 27 getTarget: function(event) { 28 return event.target || event.srcElement; 29 }, 30 //阻止事件冒泡 31 stopPropagation: function(event) { 32 if(event.stopPropagation) { 33 event.stopPropagation(); 34 } else { 35 event.cancelBubble = true; 36 } 37 }, 38 //取消事件默认行为 39 preventDefault: function(event) { 40 if(event.preventDefault) { 41 event.preventDefault(); 42 } else { 43 event.returnValue = false; 44 } 45 }, 46 //获取相关元素 47 getRelatedTarget: function(event) { 48 if(event.relatedTarget) { 49 return event.relatedTarget; 50 } else if(event.fromElement) { 51 return event.fromElement; 52 } else if(event.toElement) { 53 return event.toElement; 54 } else { 55 return null; 56 } 57 } 58 }
相关元素的示例:
1 var btn = document.getElementById("btn"); 2 event_util.addHandler(btn, "mouseover", function(event) { 3 event = event_util.getEvent(event); 4 var relatedTarget = event_util.getRelatedTarget(event); 5 var target = event_util.getTarget(event); 6 alert("光标从" + relatedTarget.tagName + "移动到" + target.tagName); 7 });
注意:Javascript中的tagName都是大写。
鼠标按钮
对于mousedown和mouseup事件而言,在event事件对象中存在一个button属性,表示按下或释放的按钮。
DOM中的button属性可能有以下三个值:0,表示主鼠标按钮;1,表示中间按钮;2,表示次鼠标按钮。
IE8及之前版本中,也提供button属性,但其属性值与DOM的不太通属性值有很大差别。
再为event_util对象添加getButton()方法。
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,就必须对相应的值进行规范化。
附上event_util对象的完整代码:
1 var event_util = { 2 //添加事件 3 addHandler: function(element, type, handler) { 4 if(element.addEventListener) { 5 element.addEventListener(type, handler, false); 6 } else if(element.attachEvent) { 7 element.attachEvent("on" + type, handler); 8 } else { 9 element["on" + type] = handler; 10 } 11 }, 12 //移除事件 13 removeHandler: function(element, type, handler) { 14 if(element.removeEventListener) { 15 element.removeEventListener(type, handler, false); 16 } else if(element.detachEvent) { 17 element.detachEvent("on" + type, handler); 18 } else { 19 element["on" + type] = null; 20 } 21 }, 22 //获取事件对象 23 getEvent: function(event) { 24 return event ? event : window.event; 25 }, 26 //获取事件目标 27 getTarget: function(event) { 28 return event.target || event.srcElement; 29 }, 30 //阻止事件冒泡 31 stopPropagation: function(event) { 32 if(event.stopPropagation) { 33 event.stopPropagation(); 34 } else { 35 event.cancelBubble = true; 36 } 37 }, 38 //取消事件默认行为 39 preventDefault: function(event) { 40 if(event.preventDefault) { 41 event.preventDefault(); 42 } else { 43 event.returnValue = false; 44 } 45 }, 46 //获取相关元素 47 getRelatedTarget: function(event) { 48 if(event.relatedTarget) { 49 return event.relatedTarget; 50 } else if(event.fromElement) { 51 return event.fromElement; 52 } else if(event.toElement) { 53 return event.toElement; 54 } else { 55 return null; 56 } 57 }, 58 //获取button属性值 59 getButton: function(event) { 60 if(document.implementation.hasFeature("MouseEvents", "2.0")) { 61 return event.button; 62 } else { 63 switch(event.button) { 64 case 0: 65 case 1: 66 case 3: 67 case 5: 68 case 7: 69 return 0; 70 case 2: 71 case 6: 72 return 2; 73 case 4: 74 return 1; 75 } 76 } 77 } 78 }
鼠标按钮示例:
1 event_util.addHandler(document, "click", function(event) { 2 event = event_util.getEvent(event); 3 alert(event.button); 4 });
更多的事件信息
对于鼠标事件来说,detail属性中包含一个数值,表示在给定位置上发生多少次单击;在同一个位置上相继发生mousedown和mouseup事件算作一次单击。
detail从1开始计数。
如果鼠标在mousedown和mouseup事件之间移动了位置,则detail的值会被重置为0。
鼠标滚轮事件
mousewheel事件,可以在任何元素上触发,最终会冒泡到document(IE8)或window(IE9、Opera、Chrome和Safari)对象。
与mousewheel事件对应的event对象除了包含鼠标事件的所有标准信息之外,还包含一个特殊的wheelDelta属性;当用户向前滚动鼠标滚轮时,wheelDelta是10的倍数,当用户向后滚动鼠标滚轮时,wheelDelta是-120的倍数。
1 event_util.addHandler(document, "mousewheel", function(event) { 2 event = event_util.getEvent(event); 3 alert(event.wheelDelta); 4 });
多数情况下,只需要知道滚动鼠标滚轮的方向,而这通过检测wheelDelta的正负号就可以确定。
在Opera9.5及之前版本中,wheelDelta的正负号是颠倒的;可以使用浏览器检测技术来确定实际的值,如下:
1 event_util.addHandler(document, "mousewheel", function(event) { 2 event = event_util.getEvent(event); 3 var delta = (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta) 4 alert(delta); 5 });
在Firefox浏览器中,支持一个名为DOMMouseScroll的事件,也是在鼠标滚轮滚动时触发,其被视为鼠标事件,包含与鼠标事件有关的所有信息;而有关鼠标滚轮的信息则保存在detail属性中,当向前滚动滚轮时,其值为-3的倍数,当向后滚动滚轮时,其值为3的倍数。
可以将DOMMouseScroll事件添加到页面中的任何元素,而且该事件会冒泡到window对象。
1 event_util.addHandler(document, "DOMMouseScroll", function(event) { 2 event = event_util.getEvent(event); 3 alert(event.detail); 4 });
跨浏览器的解决方案
首先,创建一个能够取得鼠标滚轮增量值(delta)的方法getWheelDelta()。
1 getWheelDelta: function(event) { 2 if(event.wheelDelta) { 3 return event.wheelDelta; 4 } else { 5 return -event.detail * 40; 6 } 7 }
首先检测事件中是否包含wheelDelta属性,如果是,则通过wheelDelta属性返回值;如果不存在wheelDelta属性,则假设相应的值保存在detail属性中,将这个值取反然后乘以40,就可以得到与其它浏览器相同的值。
上述代码暂不考虑Opera9.5及之前的情况。
将这个方法添加到event_util对象中;附上event_util对象完整代码:
1 var event_util = { 2 //添加事件 3 addHandler: function(element, type, handler) { 4 if(element.addEventListener) { 5 element.addEventListener(type, handler, false); 6 } else if(element.attachEvent) { 7 element.attachEvent("on" + type, handler); 8 } else { 9 element["on" + type] = handler; 10 } 11 }, 12 //移除事件 13 removeHandler: function(element, type, handler) { 14 if(element.removeEventListener) { 15 element.removeEventListener(type, handler, false); 16 } else if(element.detachEvent) { 17 element.detachEvent("on" + type, handler); 18 } else { 19 element["on" + type] = null; 20 } 21 }, 22 //获取事件对象 23 getEvent: function(event) { 24 return event ? event : window.event; 25 }, 26 //获取事件目标 27 getTarget: function(event) { 28 return event.target || event.srcElement; 29 }, 30 //阻止事件冒泡 31 stopPropagation: function(event) { 32 if(event.stopPropagation) { 33 event.stopPropagation(); 34 } else { 35 event.cancelBubble = true; 36 } 37 }, 38 //取消事件默认行为 39 preventDefault: function(event) { 40 if(event.preventDefault) { 41 event.preventDefault(); 42 } else { 43 event.returnValue = false; 44 } 45 }, 46 //获取相关元素 47 getRelatedTarget: function(event) { 48 if(event.relatedTarget) { 49 return event.relatedTarget; 50 } else if(event.fromElement) { 51 return event.fromElement; 52 } else if(event.toElement) { 53 return event.toElement; 54 } else { 55 return null; 56 } 57 }, 58 //获取button属性值 59 getButton: function(event) { 60 if(document.implementation.hasFeature("MouseEvents", "2.0")) { 61 return event.button; 62 } else { 63 switch(event.button) { 64 case 0: 65 case 1: 66 case 3: 67 case 5: 68 case 7: 69 return 0; 70 case 2: 71 case 6: 72 return 2; 73 case 4: 74 return 1; 75 } 76 } 77 }, 78 //获取鼠标滚轮增量值 79 getWheelDelta: function(event) { 80 if(event.wheelDelta) { 81 return event.wheelDelta; 82 } else { 83 return -event.detail * 40; 84 } 85 } 86 }
定义一个handleWheelDelta函数,作为一个事件处理程序,可以同时应对FIrefox中的“DOMMouseScroll”事件和非Firefox中的“mousewheel”事件。
1 function handleMouseWheel(event) { 2 event = event_util.getEvent(event); 3 var delta = event_util.getWheelDelta(event); 4 alert(delta); 5 }
可以使用以下代码来添加事件:
1 event_util.addHandler(document, "DOMMouseScroll", handleMouseWheel); 2 event_util.addHandler(document, "mousewheel", handleMouseWheel);
可以进一步将这些代码放在一个私有作用域中,从而不会让新定义的函数干扰全局作用域。
1 (function() { 2 function handleMouseWheel(event) { 3 event = event_util.getEvent(event); 4 var delta = event_util.getWheelDelta(event); 5 alert(delta); 6 } 7 event_util.addHandler(document, "DOMMouseScroll", handleMouseWheel); 8 event_util.addHandler(document, "mousewheel", handleMouseWheel); 9 })();
触摸设备
(1)不支持dbclick事件。双击浏览器窗口会放大画面,而且没有办法改变该行为。
(2)轻击可单击元素会触发mouseover事件。如果此操作导致内容变化,则不会再有其它事件发生;如果屏幕没有发生变化,则依次发生mousedown、mouseup、click事件。
(3)mousemove事件也会触发mouseover和mouseout事件。
(4)两个手指放在屏幕上且页面随手指移动而滚动时会触发mousewheel和scroll事件。
无障碍性问题
可以通过键盘上的回车键来触发click事件,而其它鼠标事件都不能通过键盘触发;因此,不建议使用其它鼠标事件来展示功能或引发代码执行,因为这样会给屏幕阅读器用户造成极大不便。
使用鼠标事件时应注意的几个易访问性问题:
(1)使用click事件执行代码。
(2)不要使用mouseover向用户显示新的选项;如果确实需要通过这种方式来显示,可以考虑添加显示相同信息的键盘快捷方式。
(3)不要使用dbclick执行重要的操作;键盘无法触发这个事件。
标签:
原文地址:http://www.cnblogs.com/cc156676/p/5742654.html