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的更多相关文章

  1. [javascript]Three parts of javascript code snippet

    <script> (function(){ /* if (navigator.userAgent.toLowerCase().indexOf("iphone") == ...

  2. javascript code snippet -- 保留小数点位数

    js1.5以上可以利用toFixed(x) ,可指定数字截取小数点后 x位 for example : //round "original" to two decimals var ...

  3. Javascript Madness: Mouse Events

    http://unixpapa.com/js/mouse.html Javascript Madness: Mouse Events Jan WolterAug 12, 2011 Note: I ha ...

  4. VS里的 代码片段(Code snippet)很有用,制作也很简单

    工欲善其事必先利其器,而 Visual Studio 就是我们的开发利器. 上一篇文章,介绍了一个很棒的快捷键,如果你还没用过这个快捷键,看完之后应该会豁然开朗.如果你已经熟练的应用它,也会温故而知新 ...

  5. 使用 Code Snippet 简化 Coding

    在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for.foreach ? 在编写这两个循环语句的时候,你是一个字符一个字符敲还是使用 Visual Studio 提 ...

  6. Visual Studio 如何使用代码片段Code Snippet提高编程速度!!!

      使用Code Snippet简化Coding 在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for.foreach ? 在编写这两个循环语句的时候,你是一个字符 ...

  7. 如何创建 Code Snippet

    比如有一行自定义代码段: @property (nonatomic,copy) NSString *<#string#>; 需要添加到 Code Snippet 上,以帮助开发人员开发更便 ...

  8. 善用VS中的Code Snippet来提高开发效率

    http://www.cnblogs.com/anderslly/archive/2009/02/16/vs2008-code-snippets.html http://www.cnblogs.com ...

  9. 介绍 .Net工具Code Snippet 与 Sql Server2008工具SSMS Tools Pack

    不久前,某某在微软写了一个很酷的工具:Visual Stuido2008可视化代码片断工具,这个工具可以在http://www.codeplex.com/SnippetDesigner上免费下载,用它 ...

随机推荐

  1. android 设置状态栏与标题背景颜色一致

    必须在Android4.4以上版本才能设置状态栏颜色: 一.在单个Activity里面,设置状态栏的背景: 效果: 1.在Activity的布局根文件中添加属性: android:fitsSystem ...

  2. PPTP-VPN第三章——用户流量与并发数限制

    在前面两篇文章中详细介绍了pptp vpn的安装与使用,以及如何配置用户认证存入mysql数据库.本文将在前面两篇文章的基础上介绍如何对用户的流量做限制,同时限制相同账号的用户,同一时刻的在线数为1. ...

  3. sscanf与正则表达式(转)

    今天翻google reader的时候看到这样一篇文章,介绍的是sscanf的高级用法.直到今天我才知道sscanf是可以直接用正则表达式的,惭愧. 在msdn中sscanf的声明如下 int ssc ...

  4. [转]CryptographyHelper.cs

    using System; using System.IO; using System.Security.Cryptography; using System.Text; public class C ...

  5. IIS内存溢出-设置IIS的应用程序池

    在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量.在machine.config(C:/WINDOWS/Microsoft.NET/Framework/v ...

  6. CoordinatorLayout+TabLayout+ViewPager

    <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.C ...

  7. CSS3 animation 的尝试

    下面是动画效果: .zoombie { width: 55px; height: 85px; background-image: url("http://images2015.cnblogs ...

  8. Error:Protocol family unavailable

    在环境变量添加:_JAVA_OPTIONS 变量值为:-Djava.net.preferIPv4Stack=true 环境变量添加方法链接: http://jingyan.baidu.com/arti ...

  9. .net学习笔记--文件读写的几种方式

    在.net中有很多有用的类库来读写硬盘上的文件 一般比较常用的有: File:1.什么时候使用:当读写件大小不大,同时可以一次性进行读写操作的时候使用         2.不同的方式可以读写文件类型不 ...

  10. Nginx-->基础-->安装-->001:安装总结

    root@ubuntu:/data/src/nginx# ./configure --help --help print this message --prefix=PATH set installa ...