用Javascript獲取元素在頁面中的絕對位置


  相信搞前端開發的朋友們都遇到過這個問題,網上有很多討論它的文章,但似乎都沒有給出一個很完美的解決方案。本文試圖用傳統的遞歸offsetLeft,offsetTop的方法來獲得元素的絕對坐標,並通過這個過程加深對DOM盒模型的理解,將其中易混淆的屬性如offsetLeft,scrollLeft分辨開來。

  1. 支持的瀏覽器

  針對目前的情況,支持ie6+, 以及firefox,chrome,opera,safari的最新版本(這里偷個懶,所以具體支持到什么版本沒有測試,但是一般而言,國內使用這些瀏覽器的用戶都會選擇較新的版本,應該沒有問題)。

  2. 測試頁面編寫

  測試頁面有內嵌的CSS元素,以及引入的Javascript代碼,即getOffset函數。測試頁面有以下幾個元素需要注意,首先就是id為target的元素,它是我們要獲取絕對坐標的元素,它存在一個div元素中,這個div元素隨着測試的進行,它的position是否為靜態,是否又邊框,是否又滾動條會發生變化,從而測試我們函數的健壯性。每次測試的觸發都是通過對id為button的元素單擊完成的,測試完成后,需要一個小元素去證明獲取的是否正確,即id為testResult的元素。id為coord元素也只是起一個坐標指示的作用,您可以忽略它。下面是html文件最終的測試版本,您如果用該文件進行測試,在接下來的每一小節的描述中,您需要自行修改CSS部分。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
    <title>測試最完整的獲取頁面Dom元素的絕對位置的函數-Get Absolute Positon of DOM Element by Javascript </title>
    <script type="text/javascript" src="getOffset.js"></script>
    <style type="text/css">
        html, body {
            margin: 0;
            padding: 0;
        }

        html {

        }

        body {
            min-height: 1200px;
            border: 10px solid red;    
            margin: 30px;
        }
    
        .wrap1 {
            background-color: #777;
        }
        .wrap2 {
            background-color: #999;
            margin-left: 20px;
        }
        .wrap3 {
            background-color: #BBB;
            margin-left: 20px;
            padding-left: 10px;
            height: 400px;
            width: 400px;
        }
        .pos-static {
            position: static;
        }
        .pos-nonstatic {
            position: relative;
            left: 50px;
            top: 10px;
        }
        .bd {
            border: 10px solid yellow;
        }
        .non-bd {
            border:none;
        }
        .scrl {
            overflow: scroll;
            height: 200px;
        }

        .non-scrl {
            overflow: auto;
        }
        #target {
            background: blue;
        }
        #testResult {
            width: 10px;
            height: 10px;
            position:absolute;
            background-color:green;
            left:0px;
            top:0px;
            z-index: 100;
        }

        #coord {
            width: 10px;
            height: 210px;
            position: absolute;
            left: 200px;
            top:0px;
            background: green;
            z-index: 400;
        }
        #seperator {
            height: 200px;
            background: white;
        }

    </style>
</head>
<body>
    <div id="testResult"></div>
    <div id="coord"></div>
    <div class="wrap1">
        <div class="wrap2 pos-nonstatic">
            <div class="wrap3 bd scrl">
                <div id="seperator">                    
                </div>
                <div id="target">My position</div>
            </div>
        </div>
        <h1>--------------------------------------------------</h1>        
    </div>
    <div id="button" style="border:1px solid;">計算 | getOffset_geetest</div>
    <div id="result">
        
    </div>
    <script type="text/javascript">
        var button = document.getElementById('button');
        var target = document.getElementById('target');
        var result = document.getElementById('result');
        var testResult = document.getElementById('testResult');

        button.onclick = function () {            
            var str = ('Ele屬性: offsetLeft:' + target.offsetLeft + ' offsetTop:' +target.offsetTop +  ' scrollLeft:' + target.scrollLeft + ' scrollTop:' +target.scrollTop + '<br />');
            var pos = getOffset_geetest_ex(target);
            str += ('getOffset:' + pos.left + ', ' + pos.top +'<br />');        
            result.innerHTML = str;

            testResult.style.left = pos.left + "px";
            testResult.style.top = pos.top + "px";
        }
    </script>
</body>
</html>

3. 最原始的getOffset函數,直接用offsetTop 和 offsetLeft遞

function getOffset(el) {
    var _x = 0, _y = 0;
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

 

4. 測試第一步,target的父元素有邊框外,無滾動,body有邊框,border為10,且body的position為relative。

可以看到初始情況下,用於測試結果的testResult小方塊正好在body的框內。如下圖所示

測試結果如下所示:

 

offsetTop

最終的top

offsetLeft

最終的left

偏移

Chrome

220

210

70

60

Firefox

210

210

60

60

Opera

220

210

70

60

IE(高)

210

210

60

60

IE(低)

200

210

10

60

  通過上表可以看出,Opera和Chrome瀏覽器的表現很一致,即他們的offsetLeft和offsetTop包含了body元素的邊框大小,而Firefox和ie則沒有包含。ie低版本是因為它的offsetLeft指向了它的父元素(position為static)。如果此時,設置body元素的margin,padding都沒有任何影響。

(待續...)

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM