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 相关文章推荐
提高代码性能技巧谈—以创建千行表格为例
Jul 01 Javascript
js操作输入框提示信息且响应鼠标事件
Mar 25 Javascript
JavaScript中的无阻塞加载性能优化方案
Oct 10 Javascript
浅谈关于JavaScript API设计的一些建议和准则
Jun 24 Javascript
JavaScript运动减速效果实例分析
Aug 04 Javascript
JavaScript encodeURI 和encodeURIComponent
Dec 04 Javascript
JavaScript动态插入CSS的方法
Dec 10 Javascript
Vue实现typeahead组件功能(非常靠谱)
Aug 26 Javascript
基于Bootstrap框架菜鸟入门教程(推荐)
Sep 17 Javascript
详解webpack编译多页面vue项目的配置问题
Dec 11 Javascript
使用js在layui中实现上传图片压缩
Jun 18 Javascript
Node 模块原理与用法详解
May 13 Javascript
由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
PHPMailer邮件类利用smtp.163.com发送邮件方法
2008/09/11 PHP
PHP SPL标准库之数据结构栈(SplStack)介绍
2015/05/12 PHP
php分割合并两个字符串的函数实例
2015/06/19 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
PHP的微信支付接口使用方法讲解
2019/03/08 PHP
laravel-admin 后台表格筛选设置默认的查询日期方法
2019/10/03 PHP
点击广告后才能获得下载地址
2006/10/26 Javascript
jQuery弹出框代码封装DialogHelper
2015/01/30 Javascript
javascript制作2048游戏
2015/03/30 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
js控住DOM实现发布微博效果
2016/08/30 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
JS中使用new Option()实现时间联动效果
2018/12/10 Javascript
使用puppeteer爬取网站并抓出404无效链接
2018/12/20 Javascript
[01:07:17]EG vs Optic Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
[01:16]DOTA2小知识课堂 Ep.03 芒果树无伤肉山
2019/12/05 DOTA
用Python编程实现语音控制电脑
2014/04/01 Python
python实现用于测试网站访问速率的方法
2015/05/26 Python
python算法演练_One Rule 算法(详解)
2017/05/17 Python
python中字符串变二维数组的实例讲解
2018/04/03 Python
使用Python实现一个栈判断括号是否平衡
2018/08/23 Python
浅谈Python中eval的强大与危害
2019/03/13 Python
Python的numpy库下的几个小函数的用法(小结)
2019/07/12 Python
Django rest framework jwt的使用方法详解
2019/08/08 Python
django框架两个使用模板实例
2019/12/11 Python
解决pytorch报错:AssertionError: Invalid device id的问题
2020/01/10 Python
pycharm通过ssh连接远程服务器教程
2020/02/12 Python
关于python tushare Tkinter构建的简单股票可视化查询系统(Beta v0.13)
2020/10/19 Python
Restful_framework视图组件代码实例解析
2020/11/17 Python
YSL圣罗兰美妆官方旗舰店:购买YSL口红
2018/04/16 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
Carolina Lemke Berlin澳大利亚官网:时尚太阳镜品牌
2019/09/17 全球购物
党员承诺践诺书
2014/05/20 职场文书
质量负责人任命书
2014/06/06 职场文书
幼儿园校园小喇叭广播稿
2014/10/17 职场文书
导游欢送词
2015/01/31 职场文书