javascript code snippet -- Forwarding Mouse Events Through Layers
Anyone who has worked with web apps has likely created a masking element at some point, and the great thing about a masking element is that it intercepts user interaction, letting us create a pseudo-modal user interface. The masking element enables us to mask the entire screen, bringing focus to a particular element, or just create a window like effect. This behavior is demonstrated in the ExtJS librariesExt.Window when modal is set to true, among other places.
Yeah, so what?
The problem comes when we want to mask a part of the screen, but also want the elements behind that mask to continue responding to user interaction. This behavior is counter to most native behavior. What we are left with, is having to forward mouse events through the masking layer to the layer below, an option that simply does not exist in the standard JavaScript/DOM API.
需要实现如下的效果,有一个浮动层,需要层级在它之下的一个元素也能照常响应相应的事件

一个100*100的元素,边框为1px solid #406c99,它有两个事件(鼠标移入、鼠标移出):
onmouseover="this.style.borderColor='#f00';"
onmouseout="this.style.borderColor='#406c99';"
在不做特殊处理的情况下,它的事件将会是无法触发的,现在想让它正常触发,效果如下:

解决这样的问题有以下方案:
1、纯使用CSS的属性pointer-events,设置其为none (默认为auto)
优点:无需额外的代码
缺点:不支持IE(IE不支持此属性,IE9是否支持有待考评..)
2、捕捉事件获取鼠标的位置X、Y,然后触发层级较低元素的相应事件 (平时我们用调试工具选取页面中的元素,高亮显示的区域就是依据这个原理)
优点:兼容各浏览器
缺点:需要编写Javascript,效率并不高
这样获取有也有两种处理方法:
循环获取每一个元素的位置,然后对比鼠标的X、Y,效率低,不推荐;这里推荐使用elementFromPoint(浏览器都支持),直接传入X、Y,便可直接获取相应的DOM元素
比较折中的办法是,针对非IE的浏览器直接使用方案1,IE使用方案2进行优化。这种应用场景,可能会是一个新的产品上线了,需要引导用户如何去使用,会使用蒙板遮住整个页面,然后让某一元素可点击。
elementFromPoint的使用例子(移动鼠标时,如果那一点在某一元素的占位区域则添加3像素的红色边框,鼠标移开该元素时清除边框)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script type="text/javascript" >
var selElem =null;
var origBorder =""; function OnMouseMove (event) {
var posX = event.clientX,
posY =event.clientY; var ua = navigator.userAgent,
isIE = /msie/i.test(ua),
isFF = /firefox/i.test(ua); if(!isIE && !isFF) {
posX = event.pageX;
posY = event.pageY;
} var info = document.getElementById("info");
info.innerHTML = event.clientX + ", " + event.clientY; var overElem = document.elementFromPoint(posX, posY); if(overElem && !overElem.tagName) {
overElem = overElem.parentNode;
} if (selElem) {
if (selElem == overElem) {
return ;
}
selElem.style.border = origBorder; selElem = null;
} if (overElem && !/^(html|body)$/.test(overElem.tagName.toLowerCase()) ) {
selElem = overElem;
origBorder = overElem.style.border;
overElem.style.border = "3px solid red" ;
}
} </script>
</head>
<body onmousemove="OnMouseMove (event);">
<div style="height:200px">
test test test test test test test
</div> <div style="position:absolute; right:20px; top:30px;">
The current mouse position: <span id="info" style="border:1px solid #606060; padding:5px;"></span>
</div>
<br/><br/>
<textarea rows="4" style="width:200px; height:100px;">
test test test test test test test test test test test test test test
</textarea> <div style="height:100px; margin-top:20px;">
test test test test test test testtest test test test test test testtest test test test test test testtest test test test test test test
</div>
</body>
</html>
遍历元素,然后找到相应的元素示例(效率比较低的一种)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>Sandbox</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
body { padding: 0px; line-height: 1.8; color: rgb(0, 128, 0);">#000; }
.box {width: 50px; height: 50px; border: 1px solid white}
.highlight {}
#controls {position:absolute; top: 300px; color: white;}
</style>
</head>
<body>
<div id="container">
<div class="box" style="position:absolute; top: 25px; left: 25px;"></div>
<div class="box" style="position:absolute; top: 50px; left: 125px;"></div>
<div class="box" style="position:absolute; top: 100px; left: 25px;"></div>
<div class="box" style="position:absolute; top: 125px; left: 180px;"></div>
<div class="box" style="position:absolute; top: 225px; left: 25px;"></div>
<div class="box" style="position:absolute; top: 185px; left: 125px;"></div>
<div id="shield" style="position: absolute; width: 200px; top: 0px; opacity: 0.5; filter:alpha(opacity=50);"></div>
</div>
<div id="controls">
<input type="checkbox" checked="checked">Pass pointer events through</input>
Try clicking
</div>
<script>
$(".box").click(function(){
$(this).toggleClass("highlight");
}); function passThrough(e) {
$(".box").each(function() {
// check if clicked point (taken from event) is inside element
var mouseX = e.pageX;
var mouseY = e.pageY;
var offset = $(this).offset();
var width = $(this).width();
var height = $(this).height(); if (mouseX > offset.left && mouseX < offset.left+width
&& mouseY > offset.top && mouseY < offset.top+height)
$(this).click(); // force click event
});
} $("#shield").click(passThrough); var dthen = new Date(); setInterval(function(){
dNow = new Date();
$('#shield').css('height', ((dNow.getSeconds()+(dNow.getMilliseconds()/1000))*50)%300 +'px');
},10) var doPassThrough = true;
$('input').click(function(){
doPassThrough = !doPassThrough;
if (doPassThrough){
$("#shield").click(passThrough);
} else {
$('#shield').unbind('click', passThrough);
}
}); </script>
</body>
</html>
在非IE浏览器中,控制pointer-events来达到想要的效果的示例
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>pointer-events test</title>
<meta name="generator" content="editplus" />
<meta name="author" content="" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-Type" content="text/html;charset=utf-8">
<style type="text/css">
* {margin:0; padding:0;}
body {width:100%; height:100%;}
</style>
</head> <body> <div style="border:1px solid #406c99; width:100px; height:100px; margin-top:300px; margin-left:300px;" onmouseover="this.style.borderColor='#f00';" onmouseout="this.style.borderColor='#406c99';" title="hahaniu"></div> <div style="position:absolute; top:0; left:0; width:100%; height:100%; opacity:.3; filter:alpha(opacity=30); overflow:hidden;" id="mask"></div> <button style="position:absolute; z-index:9999; left:100px; top:80px; padding:2px;">开启pointer-events支持</button> <script type='text/javascript'> var isOpen = false; document.getElementsByTagName("button")[0].onclick = function(evt) {
evt = evt || window.event; this.innerHTML = (isOpen ? "开启" : "关闭") + "pointer-events支持"; document.getElementById("mask").style.pointerEvents = isOpen ? "" : "none"; isOpen = !isOpen;
} </script> </body>
</html>
javascript code snippet -- Forwarding Mouse Events Through Layers的更多相关文章
- [javascript]Three parts of javascript code snippet
<script> (function(){ /* if (navigator.userAgent.toLowerCase().indexOf("iphone") == ...
- javascript code snippet -- 保留小数点位数
js1.5以上可以利用toFixed(x) ,可指定数字截取小数点后 x位 for example : //round "original" to two decimals var ...
- Javascript Madness: Mouse Events
http://unixpapa.com/js/mouse.html Javascript Madness: Mouse Events Jan WolterAug 12, 2011 Note: I ha ...
- VS里的 代码片段(Code snippet)很有用,制作也很简单
工欲善其事必先利其器,而 Visual Studio 就是我们的开发利器. 上一篇文章,介绍了一个很棒的快捷键,如果你还没用过这个快捷键,看完之后应该会豁然开朗.如果你已经熟练的应用它,也会温故而知新 ...
- 使用 Code Snippet 简化 Coding
在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for.foreach ? 在编写这两个循环语句的时候,你是一个字符一个字符敲还是使用 Visual Studio 提 ...
- Visual Studio 如何使用代码片段Code Snippet提高编程速度!!!
使用Code Snippet简化Coding 在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for.foreach ? 在编写这两个循环语句的时候,你是一个字符 ...
- 如何创建 Code Snippet
比如有一行自定义代码段: @property (nonatomic,copy) NSString *<#string#>; 需要添加到 Code Snippet 上,以帮助开发人员开发更便 ...
- 善用VS中的Code Snippet来提高开发效率
http://www.cnblogs.com/anderslly/archive/2009/02/16/vs2008-code-snippets.html http://www.cnblogs.com ...
- 介绍 .Net工具Code Snippet 与 Sql Server2008工具SSMS Tools Pack
不久前,某某在微软写了一个很酷的工具:Visual Stuido2008可视化代码片断工具,这个工具可以在http://www.codeplex.com/SnippetDesigner上免费下载,用它 ...
随机推荐
- Word2013创建目录
1.写好文档内容后,将光标移到标题行,点击“开始”里的“样式”->“创建样式”,为该标题创建一个新的样式,同时点击“修改”,在打开的窗口中选择左下方的“格式”,进行标题格式的调整.依次可设定子标 ...
- UICollectionReusableView 使用时的一些问题
在使用UICollectionView 时, 设置分区头时, - (UICollectionReusableView *)collectionView:(UICollectionView *)coll ...
- windbg学习---.browse打开一个新的command 窗口
.browse r eax .browse <command>将会显示新的命令浏览窗口和运行给出的命令
- 三张图片详解Asp.Net 全生命周期
用三张图片详解Asp.Net 全生命周期 下面我们使用三张图片解析ASP.net的整个生命周期,我总感觉使用图片更加的清楚的说明这种问题,所以使用的这样方式 说明: 1 第一张图片从全局说明从客户端 ...
- jsonp原理
http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
- 初步理解JNDI
今天初步学习了jndi的基本原理,主要是 学习了收藏中的一篇博文,讲的很好,现在记录一下自己的理解. 其实jndi就和jdbc很相似, 我们希望通过相同的jdbc api来访问不同的数据库,就必须提供 ...
- linux sysnc
rsync -az --delete --exclude="test/exclude/" test /data/sync/ 同步目录文件,排除test/exclude目录 实现目 ...
- Appium(客户端版)解决每次运行Android,都安装Appium Setting和Unlock的方法
遇到的问题:使用的Appium界面的server进行启动,每次启动时都会安装Appium Setting和Unlock文件. 通过log可以看到安装路径如下: Appium Setting安装包路 ...
- PHP实现CSV大文件数据导入到MYSQL数据库
<?php $db_host="192.168.1.10"; $db_user="root"; $db_psw="11111"; $d ...
- hashchange事件的认识
写过路由的同学都知道其原理是通过URL的改变,由导航信息来决定页面信息...表述的好像有点不准确 这么说吧,只要URL参数列表只要变化就会调用hashchange事件,此时event对象包括oldUR ...