MouseEvent鼠标事宜

DOM2级事宜中定义了7个,DOM3级事宜增加了2个鼠标事宜:

click:单击或者回车(一样平常是左按钮,可以通过键盘和鼠标进行);dbclick:双击(从技能上说,这个事宜不是DOM事宜规范中规定);mousedown:按下任意鼠标键;mouseup:开释鼠标按钮时触发;mousemove:在元素内部移动时重复地触发;mouseover:当鼠标进入元素时触发;mouseout:在鼠标光标位于一个元素上方,再将其移入另一个元素时触发;又移入的另一个元素可能位于前一个元素的外部,也可能是这个元素的子元素;mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发;类似于mouseover,但该事宜不冒泡,而且在光标移动到后代元素上不会触发,该事宜由IE引入,在DOM3级事宜中被纳入规范;mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时触发,类似于mouseout,但该事宜不冒泡,而且在光移动到后代元素上不会触发,该事宜由IE引入,在DOM3级事宜中被纳入规范;contextmenu:鼠标右击涌现高下文菜单时触发,这个事宜是在HTML5中定义的,其可以取消;

鼠标事宜中还有一类滚轮事宜,只包括一个mousewheel事宜,但此事宜已归WheelEvent类了;

html5鼠标离开事件第57节 MouseEvent鼠标事宜和WheelEvent滚轮事宜Javascript HTML

document.addEventListener("click", function(event){ console.log(event); // MouseEvent},false);document.addEventListener("mousewheel", function(event){ console.log(event); // WheelEvent},false);

可以检测浏览器是否支持所有事宜,如:

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

页面上的所有元素都支持鼠标事宜;除了mouseenter和mouseleave,其他所有鼠标事宜都会冒泡,也可以取消,而取消鼠标事宜将会影响浏览器的默认行为,也会影响其他事宜;

click事宜:

在一个元素上被按下和放开时,click事宜就会被触发,包括鼠标单击(常日是左按钮)或键盘回车,或者在脚本中为一个工具实行了click()方法也会触发该事宜;

var btn = document.getElementById("btn");btn.click();

在一个focusable元素上单击时,该元素就得到了焦点,就会触发focus事宜和click事宜;

function handler(event){console.log(event.type);}var txt = document.getElementById("txt");txt.addEventListener("click", handler,false);txt.addEventListener("focus", handler,false);

其触发的顺序为:focus、click;

只有在同一个元素上相继触发mousedown和mouseup事宜,才会触发click事宜;如果mousedown或mouseup中一个被取消,就不会触发click事宜,类似只有触发两次click事宜才会触发一次dbclick事宜;

这4个鼠标事宜触发顺序:mousedown –> mouseup –> click –> mousedown –> mouseup –> click –> dbclick;

mouseover和mouseout事宜:当鼠标进入或移出元素时触发这两个事宜;

示例:鼠标悬停改变表格行的背景色,如:

<style>#mytable{width: 400px; border-collapse: collapse;}#mytable td{ height: 20px; border: 1px solid #000;}</style><table id="mytable"><tr><td></td> <td></td> <td></td></tr><!-- 多行 --></table><script>// 表格名称、奇数行背景、偶数行背景、鼠标经由背景、点击后背景function changeBg(table, oddColor, evenColor,overColor, clickColor){var rows = document.getElementById(table).rows;for(var i=0; i < rows.length; i++){var tr = rows[i];tr.style.backgroundColor = (tr.sectionRowIndex % 2 == 0) ? oddColor : evenColor;tr.original = true;tr.addEventListener("click", function(event){if(this.original){this.original = false;this.style.backgroundColor = clickColor;}else{this.original = true;this.style.backgroundColor = (this.sectionRowIndex % 2 == 0) ? oddColor : evenColor;}});tr.addEventListener("mouseover", function(){if(this.original)this.style.backgroundColor = overColor;});tr.addEventListener("mouseout", function(){if(this.original)this.style.backgroundColor = (this.sectionRowIndex % 2 == 0) ? oddColor : evenColor;});}}changeBg("mytable", "#FFF", "#ccc", "#cfc", "#f00");</script>

mouseover和mouseout事宜会冒泡,因此,当触发mouseout事宜时,有可能鼠标真的离开了目标元素,但也有可能是从这个元素移动到它的子元素上,或者从一个子元素移动到另一个子元素,以是在这种情形下,须要判断鼠标的确切位置;

<div id="mydiv"><div id="div1">div1</div><div id="div2">div2</div></div><script>var oDiv = document.getElementById("mydiv");oDiv.addEventListener("mouseover", function(event){console.log("mouseover:" + event.target.id);},false);oDiv.addEventListener("mouseout", function(event){console.log("mouseout:" + event.target.id);},false);</script>

DOM3供应了两个不冒泡的对应版本mouseenter和mouseleave,如:

oDiv.addEventListener("mouseenter", function(event){console.log("mouseenter:" + event.target.id);},false);oDiv.addEventListener("mouseleave", function(event){console.log("mouseleave:" + event.target.id);},false);

示例:图片遮罩,如:

<style>{margin:0; padding: 0;}ul,li{list-style: none;}ul{display:flex; flex-wrap: wrap;}li{width: 200px;}li>a{display: block; width: 100%; position: relative;}li img{width:200px;}</style><ul id="mylist"><li><a href="#" title="天下第一山"><img src="images/1.jpg"></a></li><li><a href="#" title="zeronetwork"><img src="images/2.jpg"></a></li><li><a href="#" title="Javascript"><img src="images/3.jpg"></a></li><li><a href="#" title="Web前端开拓"><img src="images/4.jpg"></a></li></ul><script>window.onload = function(){var mylist = document.getElementById("mylist");var aList = mylist.getElementsByTagName("a");for(var i=0,len=aList.length; i<len; i++){var a = aList[i];var mask = null;a.addEventListener("mouseenter", function(event){mask = this.getElementsByClassName("mask")[0];if(!mask){mask = document.createElement("div");mask.className = "mask";}mask.style.backgroundColor = "rgba(0,0,0,0.8)";var computedStyle = document.defaultView.getComputedStyle(this, null);mask.style.width = computedStyle.width;mask.style.height = computedStyle.height;mask.style.position = "absolute";mask.style.color = "#FFF";mask.style.textAlign = "center";mask.style.lineHeight = computedStyle.height;mask.innerHTML = this.title;this.insertBefore(mask, this.firstChild);},false);a.addEventListener("mouseleave", function(event){var mask = this.getElementsByClassName("mask")[0];console.log(this);if(mask){this.removeChild(mask);}},false);}}</script>

mouseleave和mouseenter事宜的行为与CSS的:hover 伪类非常相似;

mousemove事宜,会频繁触发,以是,在其事宜处理程序中不能放置打算密集的任务,或者利用事宜节流的办法;

鼠标事宜工具:

鼠标事宜属于MouseEvent类,该类指的是用户与指针设备( 如鼠标 )交互时发生的事宜,其继续自UIEvent类;MouseEvent类定义了一组专属于鼠标事宜的属性,描述了当事宜发生时鼠标的位置和按键的状态,也包含了是否有赞助键被按下等所有信息;

客户区坐标位置:clientX与clientY属性:取得鼠标相对付浏览器视口的坐标位置;

var oDiv = document.getElementById("mydiv");EventUtil.addHandler(oDiv, "click", function(event){event = EventUtil.getEvent(event);console.log(event);console.log(event.clientX + "," + event.clientY);});

注,这个位置不包括页面滚动的间隔,如果加上窗口的滚动偏移量,就会把鼠标位置转换成文档坐标;所有浏览器也都实现了x和y属性,其是clientX和clientY的别名;

示例:打算鼠标拖动的直线间隔,如:

var obj = {};function downHandler(event){obj.x = event.x;obj.y = event.y;}function upHandler(event){obj.mx = event.x - obj.x;obj.my = event.y - obj.y;obj.d = Math.sqrt((Math.pow(obj.mx,2) + Math.pow(obj.my,2)));console.log(obj.mx, obj.my, obj.d);}document.addEventListener("mousedown", downHandler, false);document.addEventListener("mouseup", upHandler, false);

示例:自定义鼠标样式,如:

document.documentElement.style.cursor = "none";var cursor = document.createElement("span");cursor.style.width = "20px";cursor.style.height = "20px";cursor.style.position = "absolute";cursor.style.backgroundColor = "#000";document.body.appendChild(cursor);document.addEventListener("mousemove", function(event){cursor.style.left = event.clientX - cursor.offsetWidth / 2 + "px";cursor.style.top = event.clientY - cursor.offsetHeight / 2 + "px";},false);

文档坐标位置:pageX和pageY属性:取得鼠标光标在文档中的位置;

console.log(event.pageX + "," + event.pageY);

这个位置是包括滚动间隔的,在文档没有滚动的情形下,pageX、pageY与clientX、clientY值相等;IE8及以下不支持文档坐标,不过利用客户区坐标和滚动信息可以打算出来,也便是须要用到scrollLeft和scrollTop属性,如:

var oDiv = document.getElementById("mydiv");EventUtil.addHandler(oDiv, "click", function(event){event = EventUtil.getEvent(event);var pageX = event.pageX,pageY = event.pageY;if(pageX == undefined)pageX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);if(pageY == undefined)pageY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);console.log(pageX + ":" + pageY);});

屏幕坐标位置:screenX与screenY属性:取得相对付屏幕的位置;

console.log(event.screenX + ":" + event.screenY);

元素坐标位置:offsetX和offsetY属性,返回与目标元素(target)的内添补边(padding edge)在X和Y轴方向上的偏移量;坐标原点为padding区左上角,因此,如果目标元素有边框,鼠标的位置位于边框上,该属性值为负值;

var oDiv = document.getElementById("mydiv");oDiv.style.position = "relative";oDiv.style.left = "100px";oDiv.style.top = "50px";document.addEventListener("click", function(event){console.log("offsetX:" + event.offsetX + ",offsetY:" + event.offsetY);},false);

如果元素滚动了,也包括offsetLeft和offsetTop值;

示例:绘图:

<style>canvas{border: 1px solid;}</style><canvas id="mydraw" width="560" height="360"></canvas><script>var isDrawing = false;var x=0, y=0;var mydraw = document.getElementById("mydraw");var context = mydraw.getContext("2d");mydraw.addEventListener("mousedown", function(event){x = event.offsetX, y = event.offsetY;isDrawing = true;});mydraw.addEventListener("mousemove", function(event){if(isDrawing === true){drawLine(context, x, y, event.offsetX, event.offsetY);x = event.offsetX, y = event.offsetY;}});window.addEventListener("mouseup", function(event){if(isDrawing === true){drawLine(context, x, y, event.offsetX, event.offsetY);x = 0, y = 0;isDrawing = false;}});function drawLine(content, x1, y1, x2, y2){context.beginPath();context.strokeStyle = "black";context.lineWidth = 1;context.moveTo(x1, y1);context.lineTo(x2, y2);context.stroke();context.closePath();}</script>

movementX和movementY属性:

返回当前事宜和上一个mousemove事宜之间鼠标在水平或垂直方向上的移动值;

即:currentEvent.movementX = currentEvent.screenX - previousEvent.screenX;

currentEvent.movementY = currentEvent.screenY - previousEvent.screenY;document.addEventListener("mousemove", function(event){console.log(event.movementX);},false);

但IE不支持,并且此属性只有在mousemove事宜中才能返回精确的值;

赞助键:

DOM规定了4个属性:shiftkey、ctrlKey、altkey和metaKey,表示当事宜发生时shift、ctrl、alt和meta4个键的按下状态,均为布尔值,如果按下为true,反之为false;

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

标准浏览器支持,但IE不支持metaKey属性;

getModifierState(key)方法:返回指定润色键确当前状态;参数key可以为Control、Alt、Shift和Meta,把稳,大小写是敏感的;

btn.addEventListener("click", function(event){console.log(event.getModifierState("Control"));},false);

relatedTarget干系元素:

在发生mouseover和mouseout事宜时,会涉及到多个元素;对mouseover而言,事宜的主目标是得到光标的元素,而干系元素便是那个失落去光标的元素(这个干系元素也可以把它叫做次目标元素);对mouseout事宜而言,事宜的主目标是失落去光标的元素,而干系元素则是得到光标的元素;DOM通过event工具的relatedTarget属性供应了干系元素的信息,该属性只针于mouseover、mouseout、mouseenter、mouseleave、focusin、focusout、dragenter(拖动元素进入)事宜时才有值;对付其他事宜,该属性为null;

var oDiv = document.getElementById("mydiv");oDiv.addEventListener("mouseover", function(event){console.log(event);},false);oDiv.addEventListener("mouseout", function(event){console.log(event);},false);

IE8及以下不支持relatedTarget属性,但供应了保存着同样信息不同的属性,在mouseover事宜触发时,fromElement属性中保存了干系元素,toElement属性为事宜目标;在mouseout事宜触发时,toElement属性保存了干系元素,fromElement属性为事宜目标;

document.addEventListener("mouseover", function(event){console.log(event.fromElement);console.log(event.toElement);},false);

跨浏览器取得干系元素,添加到eventutil文件中;

getRelatedTarget: function(event){if(event.relatedTaret)return event.relatedTaret;else if(event.toElement)return event.toElement;else if(event.fromElement)return event.fromElement;elsereturn null;}

运用:

var oDiv = document.getElementById("mydiv");EventUtil.addHandler(oDiv, "mouseout", function(event){event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);var relatedTarget = EventUtil.getRelatedTarget(event);console.log(relatedTarget);console.log(relatedTarget.tagName);})

鼠标按钮:对付mousedown和mouseup事宜来说,在其event工具存在一个button属性,表示按下或开释的哪个鼠标按钮;可能有3个值:0主按钮;1中间按钮鼠标滚轮);2次按钮;

btn.addEventListener("mouseup", function(event){console.log(event.button);},false);

IE8及以下也供应了button,但其值与DOM的button属性有很大差异:0 没有按下按钮;1按下主按钮;2次按钮;3同时按下主次按钮;4中间按钮;5同时按下主和中间按钮;6次和中间按钮;7同时按下三个;

跨浏览器取得button属性,在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;}}}

buttons属性:当鼠标事宜触发的时,如果多个鼠标按钮被按下,将会返回一个或者多个代表鼠标按钮的位掩码:

0:没有按键或者是没有初始化;1:鼠标左键;2:鼠标右键;4:鼠标滚轮或者是中键;8:第四按键 (常日是“浏览器退却撤退”按键);16:第五按键 (常日是“浏览器提高”);

buttons的值为各键对应值做按位与(+)打算后的值,例如,如果右键(2)和滚轮键(4)被同时按下,buttons的值为 2 + 4 = 6,如:

btn.addEventListener("mousedown", function(event){console.log(event.button);console.log(event.buttons);},false);

属性button和buttons 是不同的,buttons可指示任意鼠标事宜中鼠标的按键情形,而 button只能担保在由按下和开释一个或多个按键时触发的事宜中得到精确的值;

which属性:当鼠标事宜触发时,表示被按下的按钮,其返回特定按键的数字,0为无、1为左键、2为中间滚轮、3为右键;其是非标准属性,但所有浏览器都支持;

btn.addEventListener("mousedown", function(event){console.log(event.which);console.log(event.button);},false);

把稳,此时该当注册mousedown或mouseup事宜而不是click事宜,由于右击或按下中间滚动不会触发click事宜;

detail属性:DOM2在event工具中供应了detail属性,用于给出有关事宜的更多信息;对付鼠标click、mousedown和mouseup事宜来说,detail中包含了一个数值,表示目标元素被单击了多少次,其它事宜返回0;detail从1开始计数,每次单击都会递增;

console.log(event.detail);

用此属性就可以判断用户是单击、双击还是三击;如果鼠标在mousedown和mouseup之间移动了位置,则detail被重置为0;

IE也通过下列属性为鼠标事宜供应了更多信息:

altLeft :布尔值,是否按下了Alt,如果为true,则altKey的值也为true;ctrlLeft:布尔值,是否按下了ctrl,如果为true,则ctrlKey的值也为true;shiftLeft:布尔值,是否按下了shift,如果为true,则shiftKey的值也为true;

这些属性只有IE支持;

示例:拖动文档元素,当鼠标按下或开释时,会触发mousedown和mouseup事宜,因此,通过这两个事宜,可以探测和相应鼠标的拖动;如:

function drag(elementToDrag, event){ var scroll = {x:0, y:0}; var startX = event.clientX + scroll.x; var startY = event.clientY + scroll.y; var origX = elementToDrag.offsetLeft; var origY = elementToDrag.offsetTop; var deltaX = startX - origX; var deltaY = startY - origY; if(document.addEventListener){ document.addEventListener("mousemove", moveHandler, true); document.addEventListener("mouseup", upHandler, true); }else if(document.attachEvent){ elementToDrag.setCapture(); elementToDrag.attachEvent("onmousemove", moveHandler); elementToDrag.attachEvent("onmouseup", upHandler); // 作为mouseup事宜看待鼠标捕获的丢失 elementToDrag.attachEvent("onlosecapture", upHandler); } // 处理了这个事宜,不让任何其他元素看到它 if(event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; // 现在阻挡任何默认操作 if(event.preventDefault) event.preventDefault(); else event.returnValue = false; // 当元素正在被拖动时,这便是捕获mousemove事宜的处理程序 // 它用于移动这个元素 function moveHandler(e){ if(!e) e = window.event; // 移动这个元素到当前鼠标位置 // 通过滚动条的位置和初始单击的偏移量来调度 // var scroll = getScrollOffsets(); var scroll = {x:0,y:0}; elementToDrag.style.left = (e.clientX + scroll.x - deltaX) + "px"; elementToDrag.style.top = (e.clientY + scroll.y - deltaY) + "px"; // 同时不让任何其他元素看到这个事宜 if(e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; } // 这是捕获在拖动结束时发生的终极mouseup事宜的处理程序 function upHandler(e){ if(!e) e = window.event; // 注销捕获事宜处理程序 if(document.removeEventListener){ document.removeEventListener("mouseup", upHandler, true); document.removeEventListener("mousemove", moveHandler, true); }else if(document.detachEvent){ elementToDrag.detachEvent("onlosecapture", upHandler); elementToDrag.detachEvent("onmouseup", upHandler); elementToDrag.detachEvent("onmousemove", moveHandler); elementToDrag.releaseCapture(); } // 并且不让事宜进一步传播 if(e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; }}

运用:

<div style="position: absolute;left:100px;top:100px; width:150px;background-color: purple;"><div style="background-color: gray;" onmousedown="drag(this.parentNode, event);">标题栏-拖动我</div><p>Lorem ...</p></div>

CSS的pointer-events属性:

指定在什么情形下 (如果有) 某个特定的元素可以成为鼠标事宜的target;紧张用于 SVG元素;可能的值为:

auto:默认效果,对付SVG内容,该值与visiblePainted效果相同;none:元素永久不会成为鼠标事宜的target;但是,当其后代元素的pointer-events属性指定其他值时,鼠标事宜可以指向后代元素,在这种情形下,鼠标事宜将在捕获或冒泡阶段触发父元素的事宜侦听器;visiblePainted、visibleFill、visibleStroke、visible、painted、fill、stroke、all;

该属性可以:

阻挡用户的点击动作产生任何效果;阻挡缺省鼠标指针的显示;阻挡CSS里的hover和active状态的变革触发事宜;阻挡JavaScript点击动作触发的事宜;

<style>/ 链接不会跳转 /a[href="https://www.zeronetwork.cn/"]{pointer-events: none;}</style><a href="https://www.zeronetwork.cn/">零点网络</a><script>var link = document.querySelector("a");function handler(event){console.log(event);}// 以下均无效link.addEventListener("click",handler,false);link.addEventListener("mouseover",handler,false);link.addEventListener("drag",handler,false);</script>

此属性可以通过掌握台改变,如在掌握台输入:document.querySelector("a").style.pointerEvents = "auto";此时,超链接就可以触发了;

<style>/ 使所有img对任何鼠标事宜(如拖动、悬停、单击等)无反应 /img{pointer-events: none;}</style><img src="images/1.jpg" /><script>var img = document.querySelector("img");function handler(event){console.log(event);}// 以下均无效img.addEventListener("click",handler,false);img.addEventListener("mouseover",handler,false);img.addEventListener("drag",handler,false);</script>

除了指示该元素不是鼠标事宜的目标之外,值none表示鼠标事宜“穿透”该元素并且指定该元素“下面”的任何元素;如:

<style>.container{position: relative; width: 200px; height: 150px;}.mask{width: 100%; height: 100%; background-color: rgba(0, 0, 0, .5);position: absolute; pointer-events: none; color:#FFF}.container img{width: 100%; height: 100%;}</style><div class="container"><div class="mask"></div><a href="https://www.zeronetwork.cn"><img src="images/1.jpg" /></a></div><script>var link = document.querySelector(".container>a");link.addEventListener("mouseover", function(event){var mask = event.currentTarget.parentNode.querySelector(".mask");mask.innerHTML = event.currentTarget.title;},false);link.addEventListener("mouseout", function(event){var mask = event.currentTarget.parentNode.querySelector(".mask");mask.innerHTML = "";},false);</script>

示例:取得一个元素的相对鼠标坐标,如:

<style>.parent{ width:400px; height:400px; padding: 50px; margin:100px; background:#f20; }.child{ width:200px; height:200px; padding:50px; background:#ff0;}.child-child{ width:50px; height:50px; background:#00d;}</style><div class="parent" id="parent"><div class="child"><div class="child-child"></div></div></div><script>var parent = document.getElementById("parent");parent.addEventListener("click",function(event){console.info(event.offsetX);});</script>

利用pointer-events属性后再获取,如为child和child-child类分别添加pointer-events属性,此时打印的值便是相对付parent元素的坐标了;

利用pointer-events来阻挡元素成为鼠标事宜目标不一定意味着元素上的事宜侦听器永久不会触发,如果元素后代明确指定了pointer-events属性并许可其成为鼠标事宜的目标,那么指向该元素的任何事宜在事宜传播过CSS添加pointer-events:none,再为其子元素添加pointer-events:all,此时在子元素上单击就可以触发注册在父元素上的事宜处理程序;

当然,位于父元素但不在后代元素上的鼠标活动都不会被父元素和后代元素捕获(鼠标活动将会穿过父元素而指向位于其下面的元素);

var subchild = document.querySelector(".child-child");subchild.addEventListener("click",function(event){console.log("child-child");parent.style.pointerEvents = "auto";});

该属性也可用来提高滚动时的帧频;例如,当页面滚动时,如果适值鼠标悬停在某些元素上,则会触发其上的hover效果或触发onmouseover事宜,有可能会造成滚动涌现问题,此时,如果对body元素运用pointer-events:none,则会禁用了包括hover在内的鼠标事宜,从而提高滚念头能;

<style>#mydiv:hover{background-color: lightgreen !important;}</style><div id="mydiv" style="height: 300px;background-color: purple;"></div><div style="height: 1000px;"></div><script>var mydiv = document.getElementById("mydiv");mydiv.addEventListener("mouseover", function(event){console.log(event);},false);</script>

滚动页面时触发了mouseover事宜及hover效果,可以在scroll事宜中进行相应的处理,如:

var timeoutId = null;window.addEventListener("scroll", function(event){document.body.style.pointerEvents = "none";if(timeoutId){clearTimeout(timeoutId);timeoutId = null;}else{timeoutId = setTimeout(function(){console.log("解禁了");document.body.style.pointerEvents = "auto";},500);}},false);

部分浏览器不支持该属性,可以判断其支持情形,如:

var supportsPointerEvents = (function(){var dummy = document.createElement("_");if(!('pointerEvents' in dummy.style))return false;dummy.style.pointerEvents = 'auto';// 如果是真的属性,则赋值不堪利dummy.style.pointerEvents = 'x';document.body.appendChild(dummy);var result = getComputedStyle(dummy).pointerEvents === 'auto';document.body.removeChild(dummy);return result;})();console.log(supportsPointerEvents);

WheelEvent滚轮事宜:

当用户通过鼠标滚轮与页面交互,在垂直方向上滚动页面时(无论向上还是向下),就会触发mousewheel事宜;该事宜可以在任何元素上触发,终极会冒泡到document或window工具,也可以阻挡其默认行为;

document.addEventListener("mousewheel", function(event){ console.log(event); // WheelEvent},false);

WheelEvent类:

表示用户滚动鼠标滚轮或类似输入设备时触发的事宜,用以替代MouseWheelEvent和MouseScrollEvent,mousewheel实际上是属于MouseWheelEvent类,而后面要讲的Firefox中的DOMMouseScroll属于MouseScrollEvent类,它们两者都不属于标准,兼容性也不好,为了统一两者,就涌现了标准的WheelEvent类;

WheelEvent类继续自MouseEvent类(MouseEvent类继续自UIEvent类),所有也可以把它看作是鼠标事宜,因此,对付WheelEvent事宜工具来说,个中也保存着大量与MouseEvent事宜同样的属性,例如,四对有关获取坐标的属性、which(值为0)、relatedTarget(为null)等等;还包括赞助键的属性;

mousewheel事宜中的event工具,除了保存鼠标事宜的所有标准信息外,还包含一个分外的wheelDelta属性,其指定用户滚动滚轮有多远,当用户向前滚动鼠标滚轮时,该属性值是120的倍数,当向后滚动时,该值是-120的倍数;

EventUtil.addHandler(document, "mousewheel", function(event){ event = EventUtil.getEvent(event); console.log(event); console.log(event.wheelDelta);})

如果要判断用户滚动的方向,只要检测wheelDelta属性的正负号即可;在Opera9.5之前的版本中,wheelDelta的值的正负号是颠倒的;

除了wheelDelta属性外,事宜工具还有wheelDeltaX和wheelDeltaY属性,并且wheelDelta和wheelDeltaY的值一贯相同;

console.log(event.wheelDelta);console.log(event.wheelDeltaY);console.log(event.wheelDeltaX);

IE不支持这两个属性;Firefox不支持mousewheel事宜,但支持一个名为DOMMouseScroll的类似事宜,也是在鼠标滚轮滚动时触发,它也被视为鼠标事宜,也包含与鼠标事宜有关的所有鼠标;而有关鼠标滚轮的信息则保存在detail属性中,该属性与wheelDelta浸染相同;当向前滚动鼠标滚轮时,该属性返回-3的位数,反之返回3的位数;

可以把该事宜添加到页面中的任何元素,而且该事宜会冒泡到window工具;

EventUtil.addHandler(document, "DOMMouseScroll", function(event){ event = EventUtil.getEvent(event); console.log(event); console.log(event.detail); // 向前为-3,向后是3})

detail属性值与wheelDelta的值的关系是:wheelDelta即是detail乘以-40;

可以跨浏览器取得鼠标滚轮增值(delta),并添加到eventutil.js中,如:

getWheelDelta: function(event){ if(event.wheelDelta){ return event.wheelDelta; }else return -event.detail 40; }

运用时,须要同时注册mousewheel和DOMMouseScroll事宜,如:

function handlerMouseWheel(event){ event = EventUtil.getEvent(event); var delta = EventUtil.getWheelDelta(event); console.log(delta);}EventUtil.addHandler(document, "mousewheel", handlerMouseWheel);EventUtil.addHandler(document, "DOMMouseScroll", handlerMouseWheel);

其余,DOMMouseEvent事宜工具中还有一个axis属性,其返回一个long型常量值,表明鼠标滚轮滚动的方向,当返回常量HORIZONTAL_AXIS,值为1时,表示由鼠标滚轮的横向滚动触发的,当返回VERTICAL_AXIS,值为2时,表示是由鼠标滚轮的纵向滚动触发的;

wheel事宜:DOM3事宜定义了一个名为wheel事宜,用于替代mousewheel和DOMMouseScroll事宜;事宜工具中保存着deltaX、deltaY及deltaZ属性:用来获取三个不同的鼠标滚轴;大多数鼠标滚轮是一维或二维的,以是并不能利用deltaZ属性;

EventUtil.addHandler(document, "wheel", function(event){ event = EventUtil.getEvent(event); console.log(event); // WheelEvent console.log(event.wheelDelta); // -120 console.log(event.wheelDeltaY); // -120 console.log(event.deltaX); // -0 console.log(event.deltaY); // chrome返回100,Firefox返回63 console.log(event.deltaZ); // 0});

这些值必须乘以-1.2,才和mousewheel事宜的wheelDelta值和正负号相匹配;

wheel事宜工具还有一个deltaMode属性,只读,其返回long常量值,表示各delta的值的单位,其值及所表示的单位如下:

常量值描述

DOM_DELTA_PIXEL0x00滚动量单位为像素DOM_DELTA_LINE0x01滚动量单位为行DOM_DELTA_PAGE0x02滚动量单位为页

console.log(event.deltaMode);

示例:在Enclose.js文件中定义enclose()函数,可以把一个图片装载到一个容器中,并且能移动这个容器,也能改变容器的大小,如:

function enclose(content, framewidth, frameheight, contentX, contentY){ // 这些参数不仅仅是初始值,它们保存当前状态,能被mousewheel处理程序利用和修正 framewidth = Math.max(framewidth, 50); frameheight = Math.max(frameheight, 50); contentX = Math.min(contentX, 0) || 0; contentY = Math.min(contentY, 0) || 0; // 创建frame元素,且设置CSS类和样式 var frame = document.createElement("div"); frame.className = "enclose"; frame.style.width = framewidth + "px"; frame.style.height = frameheight + "px"; frame.style.overflow = "hidden"; // 没有滚动条,不能溢出 frame.style.boxSizing = "border-box"; // 能简化调度frame大小的打算 content.parentNode.insertBefore(frame, content); frame.appendChild(content); // 确定元素相对付frame的位置 content.style.position = "relative"; content.style.left = contentX + "px"; content.style.top = contentY + "px"; var isFirefox = (navigator.userAgent.indexOf('Gecko') != -1); // 注册mousewheel事宜处理程序 frame.onwheel = wheelHandler; frame.onmousewheel = wheelHandler; if(isFirefox) frame.addEventListener("DOMMouseScroll", wheelHandler, false); function wheelHandler(event){ var e = event || window.event; var deltaX = e.deltaX / 3.33 || // wheel事宜 e.wheelDeltaX / 4 || // mousewheel事宜 0 // 属性未定义 var deltaY = e.deltaY / 3.33 || e.wheelDeltaY / 4 || (e.wheelDeltaY === undefined && // 如果没有2D属性 e.wheelDelta / 4) || // 就利用1D的滚轮属性 e.detail -1.2 || // DOMMouseScroll事宜 0; // 属性未定义 if(isFirefox && e.type !== "DOMMouseScroll") frame.removeEventListener("DOMMouseScroll", wheelHandler, false); // 获取内容元素确当前尺寸 var contentbox = content.getBoundingClientRect(); var contentwidth = contentbox.right - contentbox.left; var contentheight = contentbox.bottom - contentbox.top; // 如果按下Alt键,就可以调度frame大小 if(e.altKey){ if(deltaX){ framewidth -= deltaX; // 新宽度,但不能比内容大 framewidth = Math.min(framewidth, contentwidth); framewidth = Math.max(framewidth, 50); // 不能小于50 frame.style.width = framewidth + "px"; } if(deltaY){ frameheight -= deltaY; frameheight = Math.min(frameheight, contentheight); frameheight = Math.max(frameheight - deltaY, 50); frame.style.height = frameheight + "px"; } }else{ // 没有按Alt键,就可以平移frame中的内容 if(deltaX){ var minoffset = Math.min(framewidth - contentwidth, 0); // 把deltaX添加到contentX中,但不能小于minoffset contentX = Math.max(contentX + deltaX, minoffset); contentX = Math.min(contentX, 0); content.style.left = contentX + "px"; } if(deltaY){ var minoffset = Math.min(frameheight - contentheight, 0); contentY = Math.max(contentY + deltaY, minoffset); contentY = Math.min(contentY, 0); content.style.top = contentY + "px"; } } if(e.preventDefault) e.preventDefault(); if(e.stopPropagation) e.stopPropagation(); e.cancelBubble = true; e.returnValue = false; return false; }}

运用:

<style>div.enclose{border: 10px solid; margin:10px}</style><img id="content" src="images/1.jpg" /><script>window.onload = function(){ enclose(document.getElementById("content"),400,200,-200,-300);}</script>

不要稠浊wheel事宜和scroll事宜:wheel事宜的默认动作取决于浏览器实现,因此wheel事宜不一定会触发scroll事宜;即便滚轮事宜引发了文档内容的滚动行为,也不表示wheel事宜中的delta值恰好反响文档内容的滚动方向;因此,不要依赖delta属性获知文档内容的滚动方向,可在文档内容滚动事宜中监视target的scrollLeft和scrollTop的变革以推断滚动方向;