首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议135:正确获取绝对位置

关灯直达底部

任何元素都拥有offsetLeft和offsetTop属性,它们用于描述元素的偏移位置。不过不同浏览器定义元素的偏移参照对象不同,例如,IE会以父元素为参照对象进行偏移,而支持DOM标准的浏览器会以最近非静态定位元素为参照对象进行偏移。

下面的示例是一个三层嵌套的结构,其中最外层p元素被定义为相对定位显示,在JavaScript脚本中使用“alert(box.offsetLeft);”语句获取最内层p元素的偏移位置,这样IE返回值为50像素,而其他支持DOM标准的浏览器会返回101像素。注意,Opera返回值为121像素,因为它以ID为wrap元素的边框外壁为起点进行计算,而其他支持DOM标准的浏览器以ID为wrap元素的边框内壁为起点进行计算,代码如下:


<style type="text/css">

p{

width:200px;height:100px;border:solid 1px red;padding:50px;

}

#wrap{

position:relative;

border-width:20px;

}

</style>

<p>

<p>

<p></p>

</p>

</p>


获取元素的位置的呈现效果如图6.10所示。

图 6.10 获取元素的位置示意图

所有浏览器都支持offsetParent属性,该属性总能够指向定位参考的元素,并得到所有浏览器的认可,因此针对上面的嵌套结构,有如下几种情况。

❑对于IE来说,当前定位元素(即ID为box的p元素)的offsetParent属性将指向ID为sub的p元素。对于sub元素来说,它的offsetParent属性将指向ID为wrap的p元素。

❑对于支持DOM的浏览器来说,当前定位元素的offsetParent属性将指向ID为wrap的p元素。

可以根据以上情况设计一个能够兼容不同浏览器的等式:

❑IE:(#box).offsetLeft+(#sub).offsetLeft=(#box).offsetLeft+(#box).offsetParent.offsetLeft

❑DOM:(#box).offsetLeft

对于任何浏览器来说,offsetParent属性总能够自动识别当前元素偏移的参照对象,不用担心offsetParent在不同浏览器中具体指代什么元素。这样就能够通过迭代来计算当前元素距离窗口左上顶角的坐标值,具体演示如图6.11所示。

图 6.11 能够兼容不同浏览器的元素偏移位置计算演示图

虽然不同浏览器的offsetParent属性指代的元素不同,但是通过迭代计算,当前元素距离浏览器窗口的坐标距离都是相同的。因此,根据这个规律,可以设计一个扩展函数:


//获取指定元素距离窗口左上角的偏移坐标

//参数:e表示获取位置的元素

//返回值:返回对象直接量,其中属性x表示x轴偏移距离,属性y表示y轴偏移距离

function getW(e){

var x=y=0;

while(e.offsetParent){

x+=e.offsetLeft;

y+=e.offsetTop;

e=e.offsetParent;

}

return{

"x":x,

"y":y

};

}


由于body和html元素没有offsetParent属性,因此,当迭代到body元素时,会自动停止并计算出当前元素距离窗口左上角的坐标距离。

调用该扩展函数应注意:不要为包含元素定义边框,因为不同浏览器对边框的处理方式不同。例如,IE会忽略所有包含元素的边框,因为所有元素都是参照对象,并且以参照对象的边框内壁作为边线进行计算。Firefox和Safari浏览器会把静态元素的边框作为实际距离进行计算,因为对于它们来说,静态元素不作为参照对象。而对于Opera浏览器来说,由于它以非静态元素边框的外壁作为边线进行计算,所以该浏览器所获取的值又有所不同。如果不为所有包含元素定义边框,那么可以避免不同浏览器解析的分歧,最终实现返回相同的距离。