javascript 事件对象 坐标事件说明

 更新时间:2010年05月31日 23:21:18   作者:  
javascript 事件对象 坐标事件说明,学习js坐标事件的朋友可以参考下。
测试浏览器的版本:

IETester 6 ,7
IE 8.0
Firefox 3.5.5
Chrome 4.1.249.1064 (45376)
Opera 9.64
Safari 4.0


先来看看各个主流浏览器都有哪些坐标属性以及它们的意义

在IE中

event.offsetX
event.offsetY
相对于e.srcElement坐标
设置或获取鼠标指针位置相对于触发事件的对象的 x 坐标。
设置或获取鼠标指针位置相对于触发事件的对象的 y 坐标。


event.clientX
event.clientY
总是相对于视口
设置或获取鼠标指针位置相对于窗口客户区域的 x 坐标,其中客户区域不包括窗口自身的控件和滚动条。
设置或获取鼠标指针位置相对于窗口客户区域的 y 坐标,其中客户区域不包括窗口自身的控件和滚动条。


event.x
event.y
虽然手册上说是相对于文档,但是ie6/7 中,他们俩的值跟clientX,clientY一致
但是这并不是严重的问题,因为视口相对坐标加上滚动条已卷去高度,依然可以得到真实的x(y),这个问题在ie8的标准模式下被解决

设置或获取鼠标指针位置相对于父文档的 x 像素坐标。
设置或获取鼠标指针位置相对于父文档的 y 像素坐标。

event.screenX
event.screenY
设置或获取获取鼠标指针位置相对于用户屏幕的 x 坐标。
设置或获取获取鼠标指针位置相对于用户屏幕的 y 坐标。

在FireFox中

event.layerX
event.layerY
相对于e.srcElement坐标
设置或获取鼠标指针位置相对于触发事件的对象的 x 坐标。
设置或获取鼠标指针位置相对于触发事件的对象的 y 坐标。

event.clientX
event.clientY
总是相对于视口
设置或获取鼠标指针位置相对于窗口客户区域的 x 坐标,其中客户区域不包括窗口自身的控件和滚动条。
设置或获取鼠标指针位置相对于窗口客户区域的 y 坐标,其中客户区域不包括窗口自身的控件和滚动条。


event.pageX
event.pageY
设置或获取鼠标指针位置相对于父文档的 x 像素坐标。
设置或获取鼠标指针位置相对于父文档的 y 像素坐标。


event.screenX
event.screenY
设置或获取获取鼠标指针位置相对于用户屏幕的 x 坐标。
设置或获取获取鼠标指针位置相对于用户屏幕的 y 坐标。


实际上IE和Firefox已经囊括了所有的属性,其他的浏览器将这些属性进行了组合,但是意义完全一致

Chrome 和 Safari
Chrome和Safari这哥俩办事儿则灰常周全,它们收录了所有的坐标属性,包括

event.offsetX
event.offsetY
event.layerX
event.layerY

event.clientX
event.clientY

event.x
event.y
event.pageX
event.pageY

注意:Chrome和Safari的event.x event.y 跟IE6 7 的表现一致,它们和event.clientX,event.clientY相等


Opera坚定的走了ie6 7的道路,它拥有

event.offsetX
event.offsetY

event.clientX
event.clientY

event.x
event.y
差点就和ie一模一样,幸好它有pageX,pageY
event.pageX
event.pageY

注意:Chrome和Safari,以及 Opera 的event.x event.y 都跟IE6 7 的表现一致,它们和event.clientX,event.clientY相等,
而在ie8中,event.x,event.y 则等同于 其他浏览器的event.pageX,event.pageY


为啥米layerX和offsetX, x,和pageX会在某些浏览器里重复出现捏?
因为W3C并没有标准化这些属性,DOM3草案里MouseEvent部分沿用了DOM2的定义,只有两对属性

clientX of type long, readonly
The horizontal coordinate at which the event occurred relative to the viewport associated with the event.
clientY of type long, readonly
The vertical coordinate at which the event occurred relative to the viewport associated with the event

screenX of type long, readonly
The horizontal coordinate at which the event occurred relative to the origin of the screen coordinate system.
screenY of type long, readonly
The vertical coordinate at which the event occurred relative to the origin of the screen coordinate system.

这下杯具了,所以支持标准的浏览器们都木有了方向,但是吧,浏览器厂商转念一想,W3C反正也弄不出幺蛾子来,肯定从offsetXY 和 layerXY,
pageXY 和 xy中间挑一个,于是为了迎合标准,就把这两对属性就都放进了浏览器中。

不管怎么样,出了问题总是要解决掉。看到上面的兼容报告,代码雏形也就做好了

我们开始动手写!

getEventCoord
复制代码 代码如下:

1 var getEventCoord = function( e )
2 {
3 var evt = e||event;
4 var html = document.documentElement; //滚动条在<HTML>上
5 return {
6
7 //如果pageX属性为真 就使用pageX,否则就使用 clientX + html.scrollLeft
8 pageX : evt.pageX || evt.clientX + html.scrollLeft,
9
10 //如果pageY属性为真 就使用pageY,否则就使用 clientY + html.scrollTop
11 pageY : evt.pageY || evt.clientY + html.scrollTop,
12
13 //clientX Y 大家都一致,木有悬念
14 clientX : evt.clientX,
15 clientY : evt.clientY,
16
17 //如果layerX属性为真 就使用layerX,否则就使用 offsetX
18 layerX : evt.layerX || evt.offsetX,
19
20 //如果layerY属性为真 就使用layerY,否则就使用 offsetY
21 layerY : evt.layerY || evt.offsetY
22 }
23 }


用法如下
复制代码 代码如下:

document.onmousemove = function( e )
{
var coord = getEventCoord(e);
document.title = [coord.pageX,coord.pageY];
}


看起来已经灰常的OK,似乎已经能满足日常工作需要了,但还是存在几个问题

1.不严谨

使用 evt.pageX || evt.clientX + html.scrollLeft 这种判断,
只要evt.pageX 等于 undefined,null,NaN,'',0,false 这些值,左边的表达式结果就为false,从而计算右边的表达式并返回表达式的值,
而evt.pageX本身就是有机会返回0的。所以这条判断应该改为
typeof evt.pageX == 'number' ? evt.pageX : evt.clientX + html.scrollLeft
pageX是个数字的时候我们才使用它

2.无法工作在怪异模式中

什么是怪异模式?

IE为了兼容IE56之前版本,在ie6中引入了两种渲染模式: 怪异模式(Quicks Mode) 和 标准模式 (Standards Mode)
两种模式差异主要集中在css的盒模型解释方面,而BOM中。则是滚动条的依赖对象发生了变化
在怪异模式中,滚动条是body的,如果想取得页面的滚动卷去的高度和宽度,需要使用document.body.scrollTop
而标准模式中需要使用document.documentElement.scrollTop

而两种模式的切换方式主要是由doctype来确定,参见:http://dancewithnet.com/2009/06/14/activating-browser-modes-with-doctype/

从ie6开始,ie使用一个属性 document.compatMode 来检测文档是否切换到了怪异模式还是处在标准模式
如果document.compatMode的值
为BackCompat:就是在怪癖模式下
为CSS1Compat:就是在标准模式下


所以这里为了在两个模式中都工作正常,
我们需要判断document.compatMode是哪个模式
而判断的方式也很简单,只需要判断compatMode的值的第一个字母是否为b,就可以选择scrollTop的依赖对象
判断方式可以这么写
document.compatMode.indexOf('b')==0
也可以用正则写
/^b/i.test( document.compatMode )
第二种显得更牛x一点。。嗯,就用第二种(实际上第一种性能好一点)

现在再来写第二版吧

代码
复制代码 代码如下:

var getEventCoord = function( e )
{
var evt = e||event, d = document,
scrollEl = /^b/i.test( d.compatMode ) ? d.body : d.documentElement,
supportPage = typeof evt.pageX == 'number',
supportLayer = typeof evt.layerX == 'number'
return {
pageX : supportPage ? evt.pageX : evt.clientX + scrollEl.scrollLeft,
pageY : supportPage ? evt.pageY : evt.clientY + scrollEl.scrollTop,
clientX : evt.clientX,
clientY : evt.clientY,
layerX : supportLayer ? evt.layerX : evt.offsetX,
layerY : supportLayer ? evt.layerY : evt.offsetY
}
}


噔噔噔噔,这就搞定了,这个函数能干啥哩,首先想到的就是拖拽,让我们写一个小小的拖拽函数验证一下下

代码
复制代码 代码如下:

function dragMe( o )
{
var supportCapt = !!o.setCapture;
o.onmousedown = function(e)
{
var coord = getEventCoord(e), x = coord.layerX, y = coord.layerY;
if( supportCapt ) o.setCapture();
document.onmousemove = function(e)
{
var coord = getEventCoord(e);
o.style.left = coord.pageX - x + 'px';
o.style.top = coord.pageY - y + 'px';
}
document.onmouseup = function()
{
this.onmousemove = this.onmouseup = null;
if( supportCapt ) o.releaseCapture();
}
}
}
dragMe( document.getElementById('block') );

例子

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

相关文章

  • 基于javascript实现单选及多选的向右和向左移动实例

    基于javascript实现单选及多选的向右和向左移动实例

    这篇文章主要介绍了基于javascript实现单选及多选的向右和向左移动,涉及javascript针对页面元素的动态操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • webpack自动刷新浏览器源码解析

    webpack自动刷新浏览器源码解析

    Webpack自动刷新浏览器是一项非常实用的功能,它可以让开发者在编辑代码时,自动更新浏览器,从而节省大量的时间。那么它是如何实现的呢?
    2023-02-02
  • 详解如何消除axios拦截中的if

    详解如何消除axios拦截中的if

    在使用vue的开发中,我们会使用axios来做前后端通信,那这时候我们就需要对请求前后做拦截,下面这篇文章主要给大家介绍了关于如何消除axios拦截中if的相关资料,需要的朋友可以参考下
    2022-04-04
  • JavaScript era库的使用详解

    JavaScript era库的使用详解

    这篇本文主要给大家介绍了JavaScript era库的使用,使用 ora 这个 JavaScript 库可以在命令行应用程序中提供漂亮的加载状态提示,本文详细介绍如何使用该库,并结合多个例子演示其功能,需要的朋友可以参考下
    2024-02-02
  • JavaScript中函数(Function)的apply与call理解

    JavaScript中函数(Function)的apply与call理解

    这篇文章主要介绍了JavaScript中函数(Function)的apply与call理解,本文讲解了JavaScript函数调用分为4中模式以及通过apply和call实现扩展和继承两方面,需要的朋友可以参考下
    2015-07-07
  • JavaScript快速排序(quickSort)算法的实现方法总结

    JavaScript快速排序(quickSort)算法的实现方法总结

    快速排序的思想式 分治法,选一个基准点,然后根据大小进行分配,分配然完毕之后,对已经分配的进行递归操作,最终形成快速排序,所以递归也是快速排序思想的一个重要组成部分,本文主要给大家介绍了JavaScript实现快速排序的写法,需要的朋友可以参考下
    2023-11-11
  • javascript+mapbar实现地图定位

    javascript+mapbar实现地图定位

    地图定位 图吧地图定位 附javascript源码每行都有注释
    2010-04-04
  • 使用iframe实现pdf文件预览功能

    使用iframe实现pdf文件预览功能

    这篇文章主要为大家详细介绍了如何使用iframe实现pdf文件预览功能,以及iframe预览报错问题和iframe未能加载PDF文档,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-09-09
  • JS日期格式化之javascript Date format

    JS日期格式化之javascript Date format

    这篇文章主要介绍了JS日期格式化之javascript Date format的相关资料,需要的朋友可以参考下
    2015-10-10
  • 微信小程序之video组件视频播放

    微信小程序之video组件视频播放

    video控件是微信小程序提供的系统组件之一,用于实现播放视频的功能,这篇文章主要给大家介绍了关于微信小程序之video组件视频播放的相关资料,需要的朋友可以参考下
    2022-04-04

最新评论