精确获取页面元素的位置

更新日期: 2019-04-10 阅读: 2.6k 标签: 元素 作者: 司徒正美

现在网上最流行方法是John Resig在《Pro JavaScript techniques》提出的offset大法,累加元素offsetParent的offsetLeft和offsetTop一直到dom的顶层。 

//取得元素x坐标  
function pageX(elem) {
return elem.offsetParent?(elem.offsetLeft+pageX(elem.offsetParent)):elem.offsetLeft;
}
//取得元素y坐标
function pageY(elem) {
return elem.offsetParent?(elem.offsetTop+pageY(elem.offsetParent)):elem.offsetTop;
}

貌似这位大神在出这本书时比较赶,有许多纰漏,最后大神也发觉这两个函数有问题,并没有把它们运用到jquery中。由于是用累加的方式去计算,只要一个元素出现问题,就有可能层层被大,因此我在精确获取样式属性时就摒弃这种方法。主要误算参照大神的结论:

  • Handling table border offsets.
  • Fixed positioned elements.
  • Scroll offsets within another element.
  • Borders of overflowed parent elements.
  • Miscalculation of absolutely positioned elements.

随着新锐浏览器都支持IE的getBoundingClientRect方法,我们得以用更简单更快捷更安全的方法来定位页面元素。getBoundingClientRect返回的是一个集合,分别为元素在浏览器可视区的四个角的坐标。

不过它在IE的标准模式存在一个奇怪的问题,html元素是有border的,默认是2px,并且是不可修改的;怪癖模式是没有的。

This method retrieves an object that exposes the left, top, right, and bottom coordinates of the union of rectangles relative to the client's upper-left corner. In Microsoft Internet Explorer 5, the window's upper-left is at 2,2 (pixels) with respect to the true client.

我们做一些测试(请分别在IE6与IE8中进行):

1、标准模式,没有重设html的border

<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<style type="text/css">
html, body{
/* border: 0; */
}
</style>
<script type="text/javascript">
var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true : false : ((document.compatMode=="CSS1Compat") ? false : true);
var getCoords = function(el){
var box = el.getBoundingClientRect(),
top = box.top,
left = box.left
return { top: top, left: left };
};
var text = function(){
var r = getCoords(document.documentElement)
alert( r.top+","+r.left);
alert( document.documentElement.clientLeft)
if(isQuirk){
alert("怪癖模式");
}else{
alert("标准模式");
}
}
</script>
<title>getBoundingClientRect</title>
</head>
<body>
<p><button type="button" onclick="text()" >运行代码</button></p>
</body>
</html>

2、标准模式,重设html的border 

<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<style type="text/css">
html, body{
border: 0;
}
</style>
<script type="text/javascript">
var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true : false : ((document.compatMode=="CSS1Compat") ? false : true);
var getCoords = function(el){
var box = el.getBoundingClientRect(),
top = box.top,
left = box.left
return { top: top, left: left };
};
var text = function(){
var r = getCoords(document.documentElement)
alert( r.top+","+r.left);
alert( document.documentElement.clientLeft)
if(isQuirk){
alert("怪癖模式");
}else{
alert("标准模式");
}
}
</script>
<title>getBoundingClientRect</title>
</head>
<body>
<p><button type="button" onclick="text()" >运行代码</button></p>
</body>
</html>

3、怪癖模式,没有重设html的border 

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
html, body{
/* border: 0; */
}
</style>
<script type="text/javascript">
var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true : false : ((document.compatMode=="CSS1Compat") ? false : true);
var getCoords = function(el){
var box = el.getBoundingClientRect(),
top = box.top,
left = box.left
return { top: top, left: left };
};
var text = function(){
var r = getCoords(document.documentElement)
alert( r.top+","+r.left);
alert( document.documentElement.clientLeft)
if(isQuirk){
alert("怪癖模式");
}else{
alert("标准模式");
}
}
</script>
<title>getBoundingClientRect</title>
</head>
<body>
<p><button type="button" onclick="text()" >运行代码</button></p>
</body>
</html>

4、怪癖模式,重设html的border 

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
html, body{
border: 0;
}
</style>
<script type="text/javascript">
var isQuirk = document.documentMode ? document.documentMode == 5 : document.compatMode && document.compatMode != "CSS1Compat";
var getCoords = function(el){
var box = el.getBoundingClientRect(),
top = box.top,
left = box.left
return { top: top, left: left };
};
var text = function(){
var r = getCoords(document.documentElement)
alert( r.top+","+r.left);
alert( document.documentElement.clientLeft)
if(isQuirk){
alert("怪癖模式");
}else{
alert("标准模式");
}
}
</script>
<title>getBoundingClientRect</title>
</head>
<body>
<p><button type="button" onclick="text()" >运行代码</button></p>
</body>
</html>

John Resig给出的方案就是用clientTop,clientLeft作减值。以下函数就是从JQuery中抠出来,就后就用它获取页面元素的坐标,比offset大法安全多了。 

var getCoords = function(el){
var box = el.getBoundingClientRect(),
doc = el.ownerDocument,
body = doc.body,
html = doc.documentElement,
clientTop = html.clientTop || body.clientTop || 0,
clientLeft = html.clientLeft || body.clientLeft || 0,
top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop ) - clientTop,
left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft
return { 'top': top, 'left': left };
};

其中self.pageYOffset相当于window.self.pageYOffset,是火狐的一个属性,相当于document.body.scrollTop。以下是它的定义:

Definition: The pageYOffset property is used to determine the Y coordinate of the scroll position in some browsers. This is not a reserved word so you can declare your own variable or function called pageYOffset but if you do then you will not be able to find or alter the scroll position of a window in some browsers


本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/8557

相关推荐

原生JS如何获取当前元素属于父元素第几个子元素

我们经常通过document.getElementById 方法来获取到一个元素,这个时候我们经常需要有一个需求,那就是如何判断这个元素在父元素中的位置。原生JS有一个常见的小技巧那就是通过元素的previousSibling 属性,额外需要注意的是该属性会遍历text节点,即回车键。

使用原生js来控制、修改CSS伪元素的方法总汇, 例如:before和:after

在网页中,如果需要使用辅助性/装饰性的内容的时候,这就需要使用伪元素了。在使用伪元素的时候,会发现js并不真能直接控制它,这篇文章主要就介绍下如果间接的控制、修改css中伪元素的方法

js动态生成html元素并为元素追加属性

动态生成HTML元素的方法有三种:document.createElement()创建元素,再用appendChild( )添加、使用innerHTML直接将元素添加到指定节点、jQuery创建节点...

原生js删除元素

通过id删除;通过class获取元素;清空一个元素,即删除一个元素的所有子元素 ;原理很简单,就是不断的判断要清空的div还有没有子节点,有的话就删除一个子节点(这里是它的首个子节点),直到删除完毕为止。

使用document.querySelector获取元素

使用 document.querySelector() 和 document.querySelectorAll(), 将 CSS选择器 作为参数传入即可;注意: querySelecotor()返回某个元素节点, querySelectorAll()返回一个NodeList实例对象;

CSS隐藏元素的五种方法

用css隐藏页面元素有许多种方法。1、opacity:0;2、visibility:hidden;3、diaplay:none;4、position:absolute;5、clip-path。大家可以根据具体情况选择适合的方法来隐藏元素

css父元素透明度(opacity)对子元素的影响

设置父元素opacity:0.5,子元素不设置opacity,子元素会受到父元素opacity的影响,也会有0.5的透明度。设置父元素opacity:0.5,即使设置子元素opacity:1,子元素的opacity

angular怎么删除(remove)元素?

angular删除(remove)元素可以使用angular.element中的remove()方法,此方法可以将匹配元素集合从DOM中删除(同时移除元素上的事件及jQuery数据)。

JS 的 Element元素对象

在 HTML DOM 中, 元素对象代表着一个 HTML 元素。元素对象 的 子节点可以是, 可以是元素节点,文本节点,注释节点。NodeList 对象 代表了节点列表,类似于 HTML元素的子节点集合。

CSS隐藏页面元素常用方法_不同场景下使用CSS隐藏元素

使用 CSS 让元素不可见的方法很多,剪裁、定位到屏幕外、明度变化等都是可以的。虽然它们都是肉眼不可见,但背后却在多个维度上都有差别

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!