第十三章:事件类型(鼠标与滚轮事件)
来源:互联网 发布:c语言并查集简单例题 编辑:程序博客网 时间:2024/05/18 00:39
事件
事件类型
鼠标与滚轮事件
- 鼠标事件是Web开发中最常用的一类事件。DOM 3级事件中定义了9个鼠标事件,简介如下:
- click:在用户单击主鼠标按钮(一般是左键)或者按下回车键触发。这意味着onclick事件处理程序既可以通过鼠标也可以通过键盘触发。
- dblclick:双击主鼠标按钮(一般是左键)时触发。这个事件不在DOM2级事件规范中,但DOM3级事件将其纳入了标准(我试过回车按两次,没有触发)。
- mousedown:按下任意鼠标按钮时触发。不能通过键盘触发这个事件。
- mouseup:在用户释放鼠标按钮时触发。不能通过键盘触发这个事件。
- mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发。这个事件不冒泡(不冒泡决定了“移动到后代元素上不会触发”的性质),在光标移动到后代元素上不会触发。该事件也是DOM3级事件才纳入标准的。
- mouseleave:在位于元素上方的鼠标光标移动到元素范围之外(非后代元素)时触发。这个事件不冒泡,该事件也是DOM3级事件才纳入标准的。
- mousemove:当鼠标指针在元素内部移动时重复触发。不能通过键盘触发这个事件。
- mouseout:这个事件和leave的区别是,移动到的元素可以是后代元素(因为该事件会冒泡)。
- mouseover:在鼠标指针位于一个元素外部,然后首次移入该元素内部时触发(和mouseenter的区别是移动到后代元素上也会触发,因为该事件会冒泡)。不能通过键盘触发这个事件。
- 页面上的所有元素都支持鼠标事件。除了mouseenter和mouseleave,所有鼠标事件都会冒泡,也可以被取消,取消鼠标事件将会影响浏览器的默认行为。
- 只有在同一个元素上相继触发mousedown和mouseup事件,才会重触发click事件,如果其中一个被取消,则不会触发click事件。连续触发两个click事件,会触发一次dblclick事件。这4个事件的触发顺序如下:
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>Example</title></head><body> <button id="btn">xxxx</button> <script type="text/javascript"> function conlog(msg) { return function() { console.log(msg); } } var btn = document.getElementById("btn"); btn.onmousedown = conlog("mousedown!"); btn.onmouseup = conlog("mouseup!"); btn.onclick = conlog("click!"); btn.ondblclick = conlog("dblclick!"); </script></body></html>------------------双击效果如下:Chrome IE9+mousedown!mouseup!click!mousedown!mouseup!click!dblclick!------------------双击效果如下:IE8- (使用古代浏览器要注意了)日志: mousedown! 日志: mouseup! 日志: click! 日志: mouseup! 日志: dblclick!
- 使用下面的代码可以检测浏览器是否支持以上事件
var isSupported = document.implementation.hasFeature("MouseEvents", "3.0"); //后一个参数填写"2.0"则不检测dblclick、mouseenter、mouseleave
- 鼠标事件中还有一类滚轮事件。这一类事件,其实也就是一个mousewheel事件。这个事件跟踪鼠标滚轮,类似Mac的触控板。
客户区坐标位置
- 鼠标事件都是在浏览器视口中的特定位置发生的。这个位置信息保存在事件对象的clientX和clientY属性中。所有浏览器都支持这两个属性,它们的值表示鼠标指针在视口的水平和垂直坐标。
<!DOCTYPE html><html><head> <title>Client coordinates Example</title> <script type="text/javascript" src="EventUtil.js"></script></head><body> <div id="myDiv" style="background-color:red;height:100px;width:100px">Click me</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); div.onclick = function (event) { alert("Client coordinates: " + event.clientX + "," + event.clientY); } </script></body></html>
页面坐标位置
- 页面坐标位置使用事件对象的pageX和pageY属性获取(IE8-没有)。这两个属性表示鼠标光标在页面中的位置,因此坐标是从页面本身而非视口的左边和顶边计算的(虽然结果可能是一样的)。
- 在页面没有滚动的情况下,pageX和pageY与clientX和clientY的值相等
屏幕坐标位置
- 和上面的类似,事件对象还有screenX和screenY两个表示相对于电脑屏幕坐标的属性。这两个属性IE8-也支持。例子省略。
修改键
- 用过IDE写代码的都知道,比如要跳转到某个文件,我们可以在文件路径上按下ctrl键加左键跳转。在浏览器中也是类似。事件对象提供了以下4个Boolean类型的属性:
- shiftKey: true表示shift键按下
- ctrlKey
- altKey
- metaKey:在Windows中是Windows键,在Mac中是Cmd键 (IE8-不支持该属性)
<!DOCTYPE html><html><head> <title>Modifier Keys Example</title> <script type="text/javascript" src="EventUtil.js"></script></head><body> <div id="myDiv" style="background-color:red;height:100px;width:100px">Click me while holding a modifier key</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); div.onclick = function(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(",")); }; </script></body></html>
相关元素
- 在发生mouseover和mouseout事件(mouseleave和mouseenter同理)时,还会涉及更多的元素。对mouseover而言,事件的主目标是获得光标的元素,而相关元素就是那个失去光标的元素。对mouseout而言,事件的主目标是失去光标的元素,而相关元素则是获得光标的元素。相关元素的引用通过event.relatedTarget获得。需要注意的是IE8-不支持该属性,得用fromElement和toElement代替。从名字上我们可以知道fromElement存的是mouseover的相关元素,而toElement存的是mouseout的相关元素。
鼠标按钮
- event.button属性保存着按下或释放的鼠标按钮。对于mouseup和mousedown事件该属性有以下三个可能值:0表示主鼠标按钮(一般为左键);1表示中间按钮(滚轮);2表示次鼠标按钮(右键);
- IE8-之前也提供了button属性,但这个属性和DOM的button属性差异很大:
0:表示没有按下按钮。
1:表示按下了主鼠标按钮。
2:表示按下了次鼠标按钮。
3:表示同时按下了主、次鼠标按钮。
4:表示按下了中间的鼠标按钮。
5:表示同时按下了主鼠标按钮和中间的鼠标按钮。
6:表示同时按下了次鼠标按钮和中间的鼠标按钮。
7:表示同时按下了三个鼠标按钮。
更多的事件信息
- “DOM2级事件”规范在event对象中还提供了detail属性,用于给出有关事件的更多信息。对于鼠标事件来说,detail包含了一个数值,表示在给定位置上发生了多少次单击。在同一个像素上相继地发生一次mousedown和一次mouseup事件算做一次单击。detail属性从1开始每次单击后会递增。如果移动了单击位置,那肯定会重新开始计算。另外如果单击一次后停顿时间够长(我测下来一两秒左右),detail就会重新开始计数。
- IE 也通过下列属性为鼠标事件提供了更多信息。
altLeft:布尔值,表示是否按下了Alt 键。如果altLeft 的值为true,则altKey 的值也为true。
ctrlLeft:布尔值,表示是否按下了Ctrl 键。如果ctrlLeft 的值为true,则ctrlKey 的值也为true。
offsetX:光标相对于目标元素边界的x 坐标。
offsetY:光标相对于目标元素边界的y 坐标。
shiftLeft:布尔值,表示是否按下了Shift 键。如果shiftLeft 的值为true,则shiftKey的值也为true。 - 不过用处都不是很大,因为只有IE支持它们,且没有什么价值或可以通过其他方式计算得到。
鼠标滚轮事件
- IE6.0首先实现了mousewheel事件,后来各大浏览器也实现了该事件。当用户通过鼠标滚轮与页面交互、在垂直方向上滚动页面时(向上或向下)就会触发mousewheel事件。这个事件可以在任何元素上触发,最终会冒泡到document(IE8-)或window(IE9+和其余浏览器)。与mousewheel事件对应的event对象除了之前关于鼠标事件说过的属性外,还有特殊的wheelDelta属性。当用户向前(页面向上),wheelDelta是120的倍数,反之则是-120的倍数(我在Chrome上试过,滚的贼快也就出现过240,大部分时间都是120)。
触摸设备
- iOS和Android设备没有鼠标,在面向iPhone和iPod中的Safari开发时,需要注意:
- 不支持dblclick事件,因为双击浏览器会放大页面。
- 轻击可单击元素会触发mousemove 事件。如果此操作会导致内容变化,将不再有其他事件发生;如果屏幕没有因此变化,那么会依次发生mousedown、mouseup 和click 事件。轻击不可单击的元素不会触发任何事件。可单击的元素是指那些单击可产生默认操作的元素(如链接),或
者那些已经被指定了onclick 事件处理程序的元素。 - mousemove 事件也会触发mouseover 和mouseout 事件。
- 两个手指放在屏幕上且页面随手指移动而滚动时会触发mousewheel 和scroll 事件。
无障碍性问题
- 使用click 事件执行代码。有人指出通过onmousedown 执行代码会让人觉得速度更快,对视力正常的人来说这是没错的。但是,在屏幕阅读器中,由于无法触发mousedown 事件,结果就会造成代码无法执行。
- 不要使用onmouseover 向用户显示新的选项。原因同上,屏幕阅读器无法触发这个事件。如果确实非要通过这种方式来显示新选项,可以考虑添加显示相同信息的键盘快捷方式。
- 不要使用dblclick 执行重要的操作。键盘无法触发这个事件。
小结
- 总的来说几个事件还算清楚,不过mouseenter和mouseleave 与 mouseover和mouseout 还是有点混淆。我打算做几个实验来彻底理清他们。
- 首先mouseover和mouseout是冒泡的,所以意味着我给父元素设置了这两个事件,子类也可以触发他们。看下面的例子:
<!DOCTYPE html><html><head> <title>example</title> <style> td { width: 500px; height: 500px; font-size: 200px; } </style></head><body> <table id="table"> <tr id="tr1"> <td id="td1">td1</td> <td id="td2">td2</td> </tr> <tr id="tr2"> <td id="td3">td3</td> <td id="td4">td4</td> </tr> </table> <script> var fun = function(event) { var targetId = event.target.id?event.target.id:event.target.tagName; var relatedTargetid = event.relatedTarget.id?event.relatedTarget.id:event.relatedTarget.tagName; console.log("eventtype:" + event.type + " targetId:" + targetId + " relatedTargetid:" + relatedTargetid); } var table = document.getElementById("table"); table.onmouseout = fun; </script></body></html>----------------------鼠标光标从td4->td3->td1->td2->td4->htmleventtype:mouseout targetId:td4 relatedTargetid:td3eventtype:mouseout targetId:td3 relatedTargetid:td1eventtype:mouseout targetId:td1 relatedTargetid:td2eventtype:mouseout targetId:td2 relatedTargetid:td4eventtype:mouseout targetId:td4 relatedTargetid:HTML如果不小心移出浏览器的话relatedTarget会是null,这里我就不修整代码了
- 要注意mouseout和mouseleave最明显的差异就是该事件会冒泡。所以要是子元素发生了mouseout事件,会冒泡到父元素。然后再执行父元素的事件处理程序。我们把上面代码中的mouseout改成mouseleave,做一样的行为,最终只会弹出一句话:
eventtype:mouseleave targetId:table relatedTargetid:HTML
- 这是因为mouseleave事件不会冒泡,所以不论子元素发生了何种事件,父元素是不会执行事件处理程序的。而当鼠标指针移出了父元素,也就触发了父元素的mouseleave事件。不过这里有一个疑问。前面关于mouseout的例子中为何没有targetId:table relatedTargetid:HTML,而只有targetId:td4 relatedTargetid:HTML。按照这个理解应该是td4->tr2->table->html。
- (第一次猜想)猜测这里因为td和table中间没有间隙,移出td4的同时也移出了table,所以最终只检测到了td4的mouseout事件(再被冒泡), 所以才有这个现象。
- 后来我觉得上面这个猜想并不成立,因为从td4->html如果只触发td4的mouseout事件,那是不是也就意味着,这个行为也只触发td4的mouseleave事件。如果是这样,那么根本不会弹出eventtype:mouseleave targetId:table relatedTargetid:HTML。所以我打算为tr2和td4也绑定mouseleave事件处理程序。
var table = document.getElementById("table"); table.onmouseleave = fun; var tr2 = document.getElementById("tr2"); tr2.onmouseleave = fun; var td4 = document.getElementById("td4"); td4.onmouseleave = fun; //结果如下 //eventtype:mouseleave targetId:td4 relatedTargetid:HTML //eventtype:mouseleave targetId:tr2 relatedTargetid:HTML //eventtype:mouseleave targetId:table relatedTargetid:HTML
- 上面的结果说明从td4->html,是会单独触发td->html,tr->html,table->html的mouseleave事件的。那么mouseout会如何呢?
var table = document.getElementById("table"); table.onmouseout = fun; var tr2 = document.getElementById("tr2"); tr2.onmouseout = fun; var td4 = document.getElementById("td4"); td4.onmouseout = fun; //结果是连续打印三条: //eventtype:mouseout targetId:td4 relatedTargetid:HTML
- 对于第一条是可以理解的。那么后两条该如何理解呢?我们再看看currentTargetId是什么。
var fun = function(event) { var targetId = event.target.id?event.target.id:event.target.tagName; var currentTargetId = event.currentTarget.id?event.target.id:event.currentTarget.tagName; var relatedTargetid = event.relatedTarget.id?event.relatedTarget.id:event.relatedTarget.tagName; console.log("eventtype:" + event.type + " targetId:" + targetId + " relatedTargetid:" + relatedTargetid + " currentTargetId:" + currentTargetId); } var table = document.getElementById("table"); table.onmouseout = fun; var tr2 = document.getElementById("tr2"); tr2.onmouseout = fun; var td4 = document.getElementById("td4"); td4.onmouseout = fun; //事实就是,弹出了三条: //eventtype:mouseout targetId:td4 relatedTargetid:HTML currentTargetId:td4
- 这说明了,mouseout事件在子元素直接从父元素中移出,真的只会触发子元素的mouseout事件(然后冒泡给父元素)!!!我想这应该是一种优化吧。毕竟如果只为父元素绑定了mouseout事件,在子元素直接从父元素中移出,不做这种优化将会触发两次以上的mouseout事件(这只是我的个人想法)。
- 对于mouseover也是同理(也有上述我所猜想的优化行为),在子元素中移动,会触发子元素的mouseover事件,然后被父元素冒泡执行。而mouseenter由于没有冒泡,所以子元素触发的mouseenter并不会冒泡而执行父元素的事件处理程序。有兴趣的可以改下之前例子的事件名做下测试。
阅读全文
0 0
- 第十三章:事件类型(鼠标与滚轮事件)
- 事件类型--鼠标与滚轮事件
- JS鼠标与滚轮事件
- JS事件之事件类型[鼠标和滚轮事件]
- 第十三章:事件类型(HTML5事件、设备事件、触摸与手势事件)
- 鼠标滚轮事件
- javascript: 鼠标滚轮事件
- 兼容鼠标滚轮事件
- SWT:鼠标滚轮事件
- 鼠标--滚轮事件
- 鼠标滚轮事件
- 浅谈鼠标滚轮事件
- jquery 鼠标滚轮事件
- 【Js】鼠标滚轮事件
- 鼠标滚轮滚动事件
- 鼠标滚轮事件
- 鼠标滚轮事件
- js鼠标滚轮事件
- 生平第一章:关于android中的canvas的restore和save
- Kafka与其他MQ对比
- Android ADB wifi插件安装及命令行链接。附: ADB命令大全
- 如何在C++中使用cout进行高级的格式化输出操作
- Geowebcache发布ArcGIS切片的配置笔记
- 第十三章:事件类型(鼠标与滚轮事件)
- Android BroadcastReceiver 动态与静态注册
- jQuery中 html(),text(),val()的区别
- SpringMVC的工作流程
- SO抬头信息增强
- 分针网—每日分享:CSS 自定义属性:API 篇
- layui-弹出层
- 0011、node 之删除与更新用户资料
- Git建立本地仓库及各种操作命令