DOM元素的绝对位置

分享于 

7分钟阅读

Web开发

  繁體 雙語

介绍

有时( 尤其是在AJAX项目中),有必要在当前文档的"绝对"坐标中获取某些DOM元素的位置。 例如,如果希望在它的他元素的位置( 或者有一些偏移) 上显示一些隐藏的DIV 对象,则需要这样的"绝对"位置。 我们在一个项目中使用这个函数来显示一个文本标签下的弹出菜单。

解决办法是什么呢

例如 style.leftstyle.top 或者 offsetLeftoffsetTop 可以用来获取元素在其父元素内的位置。 因这里,要获得文档中元素的绝对位置,应向上移动元素树并添加元素( 除了最新的document 元素)的位置。

但是,这并不容易。 仍然存在一些问题:

  • 首先,我们需要考虑到可能滚动元素的父元素,从而减少我们的结果。
  • 其次,不同浏览器( 通常情况下:- ( )的行为有一些区别。 对于 IE,我们总是只减去存储在元素属性 offsetParent 中的对象的滚动位置。 但是对于 Firefox,我们还需要考虑 parentNode 属性可以访问的所有父对象。
  • 最后,我们应该考虑一些父元素的边框宽度。 很不幸,这个任务并不像假设那样简单,尤其是对于 IE。

下面是我们得到的函数:

function __getIEVersion() {
 var rv = -1; // Return value assumes failure.if (navigator.appName == 'Microsoft Internet Explorer') {
 var ua = navigator.userAgent;
 var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
 if (re.exec(ua)!= null)
 rv = parseFloat(RegExp.$1);
 }
 return rv;
}function __getOperaVersion() {
 var rv = 0; // Default valueif (window.opera) {
 var sver = window.opera.version();
 rv = parseFloat(sver);
 }
 return rv;
}var __userAgent = navigator.userAgent;var __isIE = navigator.appVersion.match(/MSIE/)!= null;var __IEVersion = __getIEVersion();var __isIENew = __isIE && __IEVersion> = 8;var __isIEOld = __isIE &&!__isIENew;var __isFireFox = __userAgent.match(/firefox/i)!= null;var __isFireFoxOld = __isFireFox && ((__userAgent.match(/firefox/2./i)!= null) || 
 (__userAgent.match(/firefox/1./i)!= null));var __isFireFoxNew = __isFireFox &&!__isFireFoxOld;var __isWebKit = navigator.appVersion.match(/WebKit/)!= null;var __isChrome = navigator.appVersion.match(/Chrome/)!= null;var __isOpera = window.opera!= null;var __operaVersion = __getOperaVersion();var __isOperaOld = __isOpera && (__operaVersion <10);function __parseBorderWidth(width) {
 var res = 0;
 if (typeof(width) == "string" && width!= null && width!= "" ) {
 var p = width.indexOf("px");
 if (p> = 0) {
 res = parseInt(width.substring(0, p));
 }
 else {
 //do not know how to calculate other values //(such as 0.5em or 0.1cm) correctly now//so just set the width to 1 pixel res = 1; 
 }
 }
 return res;
}//returns border width for some elementfunction __getBorderWidth(element) {
 var res = new Object();
 res.left = 0; res.top = 0; res.right = 0; res.bottom = 0;
 if (window.getComputedStyle) {
 //for Firefoxvar elStyle = window.getComputedStyle(element, null);
 res.left = parseInt(elStyle.borderLeftWidth.slice(0, -2)); 
 res.top = parseInt(elStyle.borderTopWidth.slice(0, -2)); 
 res.right = parseInt(elStyle.borderRightWidth.slice(0, -2)); 
 res.bottom = parseInt(elStyle.borderBottomWidth.slice(0, -2)); 
 }
 else {
 //for other browsers res.left = __parseBorderWidth(element.style.borderLeftWidth);
 res.top = __parseBorderWidth(element.style.borderTopWidth);
 res.right = __parseBorderWidth(element.style.borderRightWidth);
 res.bottom = __parseBorderWidth(element.style.borderBottomWidth);
 }
 return res;
}//returns the absolute position of some element within documentfunction getElementAbsolutePos(element) {
 var res = new Object();
 res.x = 0; res.y = 0;
 if (element!== null) { 
 if (element.getBoundingClientRect) {
 var viewportElement = document.documentElement; 
 var box = element.getBoundingClientRect();
 var scrollLeft = viewportElement.scrollLeft;
 var scrollTop = viewportElement.scrollTop;
 res.x = box.left + scrollLeft;
 res.y = box.top + scrollTop;
 }
 else { //for old browsers res.x = element.offsetLeft;
 res.y = element.offsetTop;
 var parentNode = element.parentNode;
 var borderWidth = null;
 while (offsetParent!= null) {
 res.x += offsetParent.offsetLeft;
 res.y += offsetParent.offsetTop;
 var parentTagName = 
 offsetParent.tagName.toLowerCase(); 
 if ((__isIEOld && parentTagName!= "table") || 
 ((__isFireFoxNew || __isChrome) && 
 parentTagName == "td")) { 
 borderWidth = kGetBorderWidth
 (offsetParent);
 res.x += borderWidth.left;
 res.y += borderWidth.top;
 }
 if (offsetParent!= document.body && 
 offsetParent!= document.documentElement) {
 res.x -= offsetParent.scrollLeft;
 res.y -= offsetParent.scrollTop;
 }
 //next lines are necessary to fix the problem //with offsetParentif (!__isIE &&!__isOperaOld || __isIENew) {
 while (offsetParent!= parentNode && 
 parentNode!== null) {
 res.x -= parentNode.scrollLeft;
 res.y -= parentNode.scrollTop;
 if (__isFireFoxOld || __isWebKit) 
 {
 borderWidth = 
 kGetBorderWidth(parentNode);
 res.x += borderWidth.left;
 res.y += borderWidth.top;
 }
 parentNode = parentNode.parentNode;
 } 
 }
 parentNode = offsetParent.parentNode;
 offsetParent = offsetParent.offsetParent;
 }
 }
 }
 return res;
}

要使用这里函数,只需将元素传递到函数的参数中,并得到 xy 属性中存储的左和顶坐标:

var pos = getElementAbsolutePos(myElement);
window.alert("Element's left:" + pos.x + " and top:" + pos.y);

在最常见的浏览器上测试了 getElementAbsolutePos 函数:

  • IE 6.0和更高版本
  • Firefox 2.x 和更高版本
  • Opera 9.x 和更高版本
  • Google Chrome

历史记录

  • 21st 2009年04月: 初始帖子
  • 28th 2009年04月: 文章已经更新
  • 20th 2011年04月: 文章已经更新

pos  DOM  绝对  
相关文章