對頁面中元素的坐標信息的獲取一直很困惑,今天在網上發現了一篇寫的還不錯的文章,翻譯出來與大家共享,有什么問題也歡迎提出來:
原文參考:(http://javascript.info/tutorial/coordinates)
元素坐標:
- 瀏覽器坐標系統
- 使用offsetParent屬性獲取元素的坐標
- 使用w3c標准屬性elem.getBoundingClientRect獲取元素的坐標
- 結合以上兩種方式,實現兼容瀏覽器的獲取坐標方式
- 摘要
在瀏覽器中存在兩個坐標系統:
- 相對文檔——坐標遠點在頁面的左上角
- 相對可視化窗口——坐標原點在可視窗口的左上角
1. 坐標系統
當頁面沒有滾動時,窗口和頁面共享相同的坐標原點,如下圖所示:
滾動后,頁面相對可視窗口發生了偏移如下圖:
事實上,在這兩種坐標系統間相互轉化很簡單,頁面坐標是窗口坐標加上頁面滾動偏移
大部分時候,僅僅使用頁面坐標,因為他們滾動后維持相同。
2. 使用offsetParent屬性獲取元素的坐標
元素的坐標是元素左上角的坐標,不幸的是沒有一個單一的屬性可以獲取到它的值,但可以是喲個offsetTop/offsetLeft和offsetParent計算它的值。
一種計算元素的絕對坐標的方式是遍歷offsetParent鏈,並對遍歷中的每個定位父元素的offsetLeft/offsetTop求和,如下所示:
1 function getOffsetSum(elem) {
3 var top=0, left=0
5 while(elem) {
7 top = top + parseInt(elem.offsetTop)
9 left = left + parseInt(elem.offsetLeft)
11 elem = elem.offsetParent
13 }
15 return {top: top, left: left}
17 }
但這種方式有兩個缺陷:
1. 它存在bug,不同的瀏覽器存在不同的問題,當考慮邊框和滾動的時候會出現問題。
2. 它計算起來很慢,每次都要遍歷整個offsetParents鏈
可以寫一個跨瀏覽器修復bug的方法,但先讓我們來看另外一種標准做法,該方法在IE6+,firefox3+ OPera ,和safrari及chrome中也支持
3. 正確的方式:elem.getBoundingClientRect
這個方式在W3C標准下有描述,大多數現代瀏覽器都支持,包括IE
它返回一個包裹元素的矩形框,這個矩形框以top , left , right , bottom四個屬性給出。
這四個數字代表了矩形的左上角和右下角的四個坐標,例如:
1 <input id="brTest" type="button" value="Show button.getBoundingClientRect()" onclick='showRect(this)'/>
2
3 <script>
4 function showRect(elem) { 5 var r = elem.getBoundingClientRect() 6 alert("Top/Left: "+r.top+" / "+r.left) 7 alert("Right/Bottom: "+r.right+" / "+r.bottom) 8 } 9 </script>
這個坐標是相對窗口,而不是相對文檔。
讓我們來看一個新版本的計算坐標的方式:使用getBoundingClientRect
1 function getOffsetRect(elem) { 2 var box = elem.getBoundingClientRect() 3 var body = document.body 4 var docElem = document.documentElement 5 var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop 6 var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft 7 var clientTop = docElem.clientTop || body.clientTop || 0
8 var clientLeft = docElem.clientLeft || body.clientLeft || 0
9 var top = box.top + scrollTop - clientTop 10 var left = box.left + scrollLeft - clientLeft 11 return { top: Math.round(top), left: Math.round(left) } 12 }
計算步驟如下:
- 獲取到包含的矩形框
- 計算頁面的滾動,除了IE<9外,所有瀏覽器都支持pageXOffset / pageYOffset,在IE中,當設置了DOCTYPE時,滾動的值可以通過documentElement獲得,否則使用body對象獲取。
- 在IE中文檔會相對左上角偏移幾個像素,需要去掉它,減去clientTop和clientLeft
- 矩形框的坐標加上頁面相對窗口滾動的坐標,減去偏移的坐標,就得到了元素相對整個文檔的坐標。
4. 跨瀏覽器兼容的解決方案:
有很多js庫結合兩種方式,獲取元素的坐標:
1 function getOffset(elem) { 2 if (elem.getBoundingClientRect) { 3 return getOffsetRect(elem) 4 } else { // old browser
5 return getOffsetSum(elem) 6 } 7 }