讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議135:正確獲取絕對位置 >

建議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瀏覽器來說,由於它以非靜態元素邊框的外壁作為邊線進行計算,所以該瀏覽器所獲取的值又有所不同。如果不為所有包含元素定義邊框,那麼可以避免不同瀏覽器解析的分歧,最終實現返回相同的距離。