相信搞前端开发的朋友们都遇到过这个问题,网上有很多讨论它的文章,但似乎都没有给出一个很完美的解决方案。本文试图用传统的递归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 ></div>
    <div ></div>
    <div class="wrap1">
        <div class="wrap2 pos-nonstatic">
            <div class="wrap3 bd scrl">
                <div >                    
                </div>
                <div >My position</div>
            </div>
        </div>
        <h1>--------------------------------------------------</h1>        
    </div>
    <div >计算 | getOffset_geetest</div>
    <div >
        
    </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的框内。如下图所示

用Javascript获取元素在页面中的绝对位置

测试结果如下所示:

 

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都没有任何影响。

(待续...)

  

 

相关文章:

  • 2022-12-23
  • 2021-12-29
  • 2021-11-23
  • 2022-03-09
  • 2021-05-22
  • 2022-01-10
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-12-22
相关资源
相似解决方案