js Event对象的5种坐标


Posted in Javascript onSeptember 12, 2011

但是你懂的,浏览器实在太不和谐了,兼容性且不说,各种坐标属性看得人头昏眼花,极容易混淆。好吧,我来总结一下:

测试浏览器:IE8, Chrome13, FF8, Safari5, Opera11
先上测试用例(用HTML5的doctype测试,也可看出未来的发展趋势,其他doctype可自行测试):

<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> 
<style type="text/css"> 
html { 
background:red; 
} 
body { 
background:green; 
} 
#null { 
height:1000px; 
} 
#btn { 
cursor:default; 
background:blue; 
width:50px; 
height:30px; 
line-height:30px; 
text-align:center; 
} 
</style> 
</head> 
<body> 
<div id='null'>空白区</div> 
<div id="btn">点击</div><!-- 按钮用DIV是因为原生按钮有圆角,不确定边界 --> 
</body> 
<script type="text/javascript"> 
window.onload = function(){ 
var btn = document.getElementById('btn'); 
btn.onclick = function(e){ 
e = e|| window.event; 
var box = (e.target || e.srcElement).getBoundingClientRect(), 
offsetX = e.clientX - box.left, 
offsetY = e.clientY - box.top; 
p('x: '+ e.x+', y: '+e.y); 
p('pageX: '+ e.pageX+', pageY: '+e.pageY); 
p('offsetX: '+ e.offsetX+', offsetY: '+e.offsetY); 
p('FF实现 offsetX: '+offsetX+', offsetY: '+offsetY); 
p('layerX: '+ e.layerX+', layerY: '+e.layerY); 
p('clientX: '+ e.clientX+', clientY: '+e.clientY); 
p('body.scrollLeft: '+ document.body.scrollLeft+', body.scrollTop: '+document.body.scrollTop); 
p('body.clientLeft: ' + document.body.clientLeft + ', body.clientTop: '+document.body.clientTop); 
p('documentElement.scrollLeft: '+ document.documentElement.scrollLeft+', documentElement.scrollTop: '+document.documentElement.scrollTop); 
p('documentElement.clientLeft: ' + document.documentElement.clientLeft + ', documentElement.clientTop: '+document.documentElement.clientTop); 
} 
} 
function p(s){ 
console.log(s); 
} 
</script> 
</html>

问:怎样获取鼠标相对于浏览器可视文档区域左上角的位置?
答:x, y和clientX, clientY皆可,但是x, y在IE下表示鼠标相对于文档开头的位置(即如果有滚到条的话,会计算在内),还有FF也不支持x, y

推荐: clientX, clientY

问:怎样获取鼠标相对于文档开头的位置?
答: IE:使用x, y(前提是事件源的父元素(一直到documentElement)没有设置position:relative之类的,否则相对于最近元素,而非相对于文档)

非IE:使用pageX, pageY

layerX, layerY其实也可以,但是IE和Opera不支持!

那么如何确保IE正常取值呢?答:event.clientX + document.documentElement.scrollLeft,

event.clientY + document.documentElement.scrollTop

问:怎样获取鼠标相对于事件源(event.target||event.srcElement)左上角的位置?
答:offsetX, offsetY。但是FF不支持,怎样办呢?

1. 先获取鼠标相对于浏览器可视文档区域左上角的位置

2. 然后获取事件源相对于浏览器可视文档区域左上角的位置

3. 相减,收工
也许有人会问,这第2步怎么做啊?好吧,好人做到底!
HTMLElement.getBoundingClientRect()方法
返回值为:{top:xx, right:xx, bottom:xx, left:xx, width:xx, height:xx}
也就是说,一个元素的位置信息都给了,我们要做的就是:

var box = (e.target || e.srcElement).getBoundingClientRect(), 
offsetX = e.clientX - box.left, 
offsetY = e.clientY - box.top;

经测试,所有浏览器都和event.offsetX, event.offsetY保持一致(当然FF除外)

我的例子中,最后还检测了scrollLeft, scrollTop, clientLeft, clientTop,本来以为它们几个会作怪,可测试结果表明:
除了scrollTop,其他都是0(当然scrollLeft是因为没出现横向滚动条所致)
scrollTop各浏览器表现不尽相同,如下:
body.scrollTop的情况

IE, FF, Opera:0

Chrome, Safari:向上滚动的距离
documentElement.scrollTop的情况

IE, FF, Opera:向上滚动的距离

Chrome, Safari:0

Javascript 相关文章推荐
newxtree.js代码
Mar 13 Javascript
jquery 最简单的属性菜单
Oct 08 Javascript
Flexigrid在IE下不显示数据的处理的解决方法
Oct 24 Javascript
javascript根据像素点取位置示例
Jan 27 Javascript
原生javascript实现图片弹窗交互效果
Jan 12 Javascript
jquery弹出遮掩层效果【附实例代码】
Apr 28 Javascript
浅谈vue实现数据监听的函数 Object.defineProperty
Jun 08 Javascript
JavaScript实现的原生态兼容IE6可调可控滚动文字功能详解
Sep 19 Javascript
防止页面url缓存中ajax中post请求的处理方法
Oct 10 Javascript
jQuery添加新内容的四个常用方法分析【append,prepend,after,before】
Mar 19 jQuery
解决vue加scoped后就无法修改vant的UI组件的样式问题
Sep 07 Javascript
vue route新窗口跳转页面并且携带与接收参数
Apr 10 Vue.js
由JavaScript中call()方法引发的对面向对象继承机制call的思考
Sep 12 #Javascript
腾讯UED 漂亮的提示信息效果代码
Sep 12 #Javascript
jQuery的.live()和.die() 使用介绍
Sep 10 #Javascript
jquery tab插件精简版分享
Sep 10 #Javascript
javascript语言结构小记(一)
Sep 10 #Javascript
JavaScript高级程序设计 客户端存储学习笔记
Sep 10 #Javascript
JavaScript高级程序设计 错误处理与调试学习笔记
Sep 10 #Javascript
You might like
使用zend studio for eclipse不能激活代码提示功能的解决办法
2009/10/11 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
php静态成员方法和静态的成员属性的使用方法
2017/10/26 PHP
PHP实现验证码校验功能
2017/11/16 PHP
PHP生成随机字符串实例代码(字母+数字)
2019/09/11 PHP
解决Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]
2020/04/06 PHP
js动态创建表格,删除行列的小例子
2013/07/20 Javascript
input:checkbox多选框实现单选效果跟radio一样
2014/06/16 Javascript
JavaScript基础函数整理汇总
2015/01/30 Javascript
jquery序列化方法实例分析
2015/06/10 Javascript
JS获取下拉框显示值和判断单选按钮的方法
2015/07/09 Javascript
js数字计算 误差问题的快速解决方法
2017/02/28 Javascript
最简单的JS实现json转csv的方法
2019/01/10 Javascript
elementUI select组件使用及注意事项详解
2019/05/29 Javascript
el-select 下拉框多选实现全选的实现
2019/08/02 Javascript
Javascript文本框脚本实现方法解析
2020/10/30 Javascript
深入解析Python编程中JSON模块的使用
2015/10/15 Python
ansible作为python模块库使用的方法实例
2017/01/17 Python
对Python进行数据分析_关于Package的安装问题
2017/05/22 Python
Python在不同目录下导入模块的实现方法
2017/10/27 Python
Python数据结构与算法之使用队列解决小猫钓鱼问题
2017/12/14 Python
TensorFlow 滑动平均的示例代码
2018/06/19 Python
python实现ip代理池功能示例
2019/07/05 Python
python路径的写法及目录的获取方式
2019/12/26 Python
详解用Python进行时间序列预测的7种方法
2020/03/13 Python
Python 使用office365邮箱的示例
2020/10/29 Python
python实现磁盘日志清理的示例
2020/11/05 Python
10分钟理解CSS3 Grid布局
2018/12/20 HTML / CSS
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
瑞典耳机品牌:URBANISTA
2019/12/03 全球购物
RUIFIER官网:英国奢侈高级珠宝品牌
2020/06/12 全球购物
市政工程技术专业自荐书
2014/07/06 职场文书
中国文明网向国旗敬礼寄语大全
2014/09/27 职场文书
社区元宵节活动总结
2015/02/06 职场文书
小学见习报告
2015/06/23 职场文书