技术分享 如何获取Dom元素的X/Y坐标
创始人
2024-07-15 03:40:34
0

当今已有很多的JS框架封装了获取Dom元素的坐标的方法,我们可以直接使用,而这里我更多的是希望透过这些方法,看到原始的获取坐标方式以及如何处理跨浏览器问题。

获取Dom元素的X/Y坐标

现在Web页面的交互方式越来越多样化,其中拖放页面元素也是一种很常见的操作。在这类操作当中有两个主要问题需要解决,一个是事件的注册方式,一般处理拖放元素的事件顺序是:捕获鼠标正键按下——注册鼠标移动事件——捕获鼠标正键抬起——注销鼠标移动事件;另一个问题就是拖放元素的位置,即X/Y坐标。这里我主要来讲述后面的问题:如何获取一个Dom元素的坐标。

当今已有很多的JS框架封装了获取Dom元素的坐标的方法,我们可以直接使用,而这里我更多的是希望透过这些方法,看到原始的获取坐标方式以及如何处理跨浏览器问题。

首先认识一下getBoundingClientRect方法,标准语法为:

  1. oRect=object.getBoundingClientRect();  
  2.  

Dom节点调用该方法可返回一个ClientRect类型的对象,该对象有四个属性值:top、left、right、bottom,表示了该节点相对于可视浏览器可视区域的左上角位置的坐标,看图就能好理解:

坐标说明图1

DOM元素坐标说明图1

补充一下,如果当前的元素已经超出可视区域,依然按照可视区域的左上角位置的坐标来计算,如图2

坐标说明图2

DOM元素坐标说明图2

这样就可以简单的获取Dom元素在可视区里的X/Y坐标(通过left和top属性)。最后在计算上页面滚动条的偏移量就可以计算出元素在整个页面中的X/Y坐标了。页面滚动偏移量的计算在不同浏览器下有所不同,不过我们可以借鉴YUI里面方法,设计一个通用的方式:

  1. scrollLeft=Math.max(document.documentElement.scrollLeft,  
  2.  
  3. document.body.scrollLeft);  
  4.  
  5. scrollTop=Math.max(document.documentElement.scrollTop,  
  6.  
  7. document.body.scrollTop);  

在W3C标准下document.body.scrollTop和document.body.scrollLeft都为0,所以采用了上面兼容的方式获取页面滚动条的偏移量。#p#

◆将ClientRect对象的left、top属性分别加上scrollLeft和scrollTop,就能获取Dom元素的X/Y坐标了。但对于IE8之前的IE版本在很多情况,下面要对这个值进行一些调整,有三种情况,下面来分别看一下:

1.IE6的标准模式下不需要调整;

2.所有怪异模式下为取document的当前borderLeftWidth和borderTopWidth值做调整,分别加在X/Y坐标值上;

3.其他的情况都分别在X/Y坐标值上加上2;

这样就可以获取最后准确的X/Y坐标了。

如果所有的浏览器都能如此就好了,可惜有些浏览器(FF2、Safari)不支持getBoundingClientRect方法。需要通过一级级查找和计算offsetParent来获取X/Y坐标值。这里首先介绍什么是元素的offsetParent属性。

◆offsetParent属性是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的与容器元素。首先说明一下CSS定位,是指对元素设置position属性为absolute、relative或fixed(IE6除外),还有一个问题是元素在table元素中时会有不同的情况。下面是我的一些归纳,不全之处望大家指出:

1.元素不在table元素中,且元素及其所有上级元素都未进行CSS定位时,这个元素的offsetParent属性为根元素(Body);

2.元素本身没进行CSS定位,而出现在table中或有上级元素进行了CSS定位,那么当向上先达到TD元素时该元素的offsetParent属性为TD元素;当向上先达到进行了CSS定位的上级元素时该元素的offsetParent属性为该上级元素;

3.无论元素在不在table中,只要元素本身进行了CSS定位,有上级元素进行了CSS定位的则元素的offsetParent属性为该上级元素,没有上级素进行了CSS定位的则元素的offsetParent属性为根元素;

知道了offsetParent属性的含义,就可以通过offsetParent属性来一级级的计算X/Y坐标了。一种比较简单的while循环:

  1. varnode;/*求坐标的元素*/  
  2. varxy=[];/*保存XY坐标*/  
  3. while((nodenode=node.offsetParent)){  
  4. xy[0]+=node.offsetLeft;  
  5. xy[1]+=node.offsetTop];  

◆通过这一个循环就能累计元素每级offsetParent属性元素的偏移量,但这个偏移量在累加的过程中没有计算每级父元素有滚动条的情况,最后还要同getBoundingClientRect方法一样加上页面滚动值(这里scrollLeft和scrollTop)。现在先来累计计算元素每上级元素的滚动条情况,首先判断元素本身是不是设置了position为fixed:

1.设置了则不用计算每上级元素的滚动条情况,但需要对Opera和其他浏览器做区分,Opera浏览器减去scrollLeft和scrollTopxy[0]-=scrollLeft;xy[1]-=scrollTop;,其他情况是加上scrollLeft和scrollTop。

  1. xy[0]+=scrollLeft;xy[1]+=scrollTop;  
  2.  

2.未设置时就需要累计计算元素每上级元素的滚动条,通过一个循环里累加:

  1. while((nodenode=node.parentNode)&&node.tagName){  
  2. scrollTop=node.scrollTop;  
  3. scrollLeft=node.scrllLeft;  
  4. if(scrollTop||scrollLeft){  
  5. xy[0]-=scrollLeft;  
  6. xy[1]-=scrollTop;  
  7. }  

最后机上页面滚动值

  1. xy[0]+=scrollLeft;xy[1]+=scrollTop;  
  2.  

这样最后就可以在不支持getBoundingClientRect方法的浏览器下获取元素的X/Y坐标了。

总结:

如果浏览器支持getBoundingClientRect方法,通过该方法再加上页面滚动条的偏移就能获取元素的X/Y了(不同浏览器需要微调),如果不支持getBoundingClientRect方法,则需要通过循环该元素的每级offsetParent属性来累计偏移量,再通过每个父级元素的滚动条来调整,最后再加上页面滚动条的偏移来获取元素的X/Y坐标。获取X/Y坐标的方式还有很多,可能不尽相同,我这里主要是基于YUI里面的思想和方法。
 

【编辑推荐】

  1. JQuery创建DOM元素方法解析
  2. W3C DOM模型用法详解
  3. JavaScript获取HTML DOM节点元素详解
  4. 深入了解JavaScript HTML DOM对象
  5. 解析HTML DOM Checkbox对象的属性和方法

 

 

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...