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上免费下载,用它 ...
随机推荐
- Ext.get Ext.getDom Ext.getCmp 的区别
Html DOM Ext Element Component Component 最高层 Html DOM 最基础 Ext.getCmp 是 Ext.ComponentMgr.get ...
- CentOS6.5源码安装python3.5.2
前提: 1.实现自动补全需要安装模块 readline-devel (yum install -y readline-devel) 2.实现支持SSL协议需安装模块 openssl-devel (yu ...
- ORACLE临时表空间
ORACLE临时表空间总结 2014-10-05 11:35 by 潇湘隐者, 临时表空间概念 临 时表空间用来管理数据库排序操作以及用于存储临时表.中间排序结果等临时对象,当ORACLE里需要用到S ...
- sql 事物以及回滚
第一种: Begin Try Begin Tran Tran1 insert into t1(Id, c1) values(1,'1') insert into t1 ...
- jQuery(window) 和 jQuery(document)的区别
jQuery(window).height()代表了当前可见区域的大小,而jQuery(document).height()则代表了整个文档的高度,可视具体情况使用
- JSP计算器
<%@ page language= "java" contentType="text/html;charset=UTF-8" %><html ...
- 解决程序出现“terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)”的问题
最近跑程序时出现了这么一个问题: terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_al ...
- NGUI 屏幕自适应大屏与小屏(初始设定宽高为1280x720,能适应比其小或者更大的屏)
具体细节可以参考另外一篇随笔! 以下提供的算法完成的事: 1.自适应1280x720分辨率以下的屏幕 2.自适应1280x720分辨率以上的屏幕 在我设定的要求内包括的分辨率大部分都测过了,背景图.全 ...
- 寒冰王座 hdu 1248(背包)
http://acm.hdu.edu.cn/showproblem.php?pid=1248 #include <stdio.h> #include <stdlib.h> #i ...
- nginx+tomcat负载均衡
最近练习nginx+tomcat负载均衡.根据一些资料整理了大体思路,最终实现了1个nginx+2个tomcat负载均衡. 安装JDK 1>进入安装目录,给所有用户添加可执行的权限 #chmod ...