jquery源码解析(第3章元素之坐标算法)

来源:互联网 发布:thinkphp分销系统源码 编辑:程序博客网 时间:2024/06/08 08:39

获取位置有 offset 与 position两个方法。

offset()
方法允许我们检索一个元素相对于文档(document)的当前位置,它和.position()的差别在于:.position()是相对于相对于父级元素的位移。

当通过全局操作(特别是通过拖拽操作)将一个新的元素放置到另一个已经存在的元素的上面时,若要取得这个新的元素的位置,那么使用 .offset() 更合适。

jQuery不支持获取隐藏元素的偏移坐标。同样的,也无法取得隐藏元素的 border, margin, 或 padding 信息。位置的方法没有像witdh/height一样去修复了 display:none 的情况。所以针对offset的定义是相对文档的,传统来说用offsetLeft和offsetTop是可以的,但是兼容各种浏览器以及各种不同的元素就会把你弄死,而且效率还非常低下。所以获取页面上某个元素相对于浏览器窗口的偏移量就成了getBoundingClientRect的用武之地了,但是还是会有一些兼容性的问题的。

在具体表现方面,Firefox6以前的版本使用getBoundingClientRect时不能获取到top和bottom这两个属性值,Firefox6及以后的版本和其他支持getBoundingClientRect方法的浏览器则top、left、right、bottom四个属性值均能获取到。需要说明的是由于某些版本的IE浏览器的文档根元素默认是有2px边框的,所以这里需要特别处理一下,微软MSDN上说在IE5中会存在这样的情况,我们只要把得到的值减去html根元素(body也可考虑进来)的clientLeft或clientTop就能保持各浏览器一致啦。

top: box.top + win.pageYOffset - docElem.clientTop,left: box.left + win.pageXOffset - docElem.clientLeft

问题:box.top指的是相对于窗口的偏移量

补充:pageXOffset 和 pageYOffset 属性返回文档在窗口左上角水平和垂直方向滚动的像素。
pageXOffset 设置或返回当前页面相对于窗口显示区左上角的 X 位置。pageYOffset 设置或返回当前页面相对于窗口显示区左上角的 Y 位置。
pageXOffset 和 pageYOffset 属性相等于 scrollX 和 scrollY 属性。
这些属性是只读的。

position()

.position()方法可以取得元素相对于父元素的偏移位置。与.offset()不同, .offset()是获得该元素相对于documet的当前坐标,当把一个新元素放在同一个容器里面另一个元素附近时,用.position()更好用。.position()返回一个包含 top 和 left 属性的对象.Position是一个相对父元素的定位所以实际的距离还要跟当然用了定位的属性有关系。

我们分析下几种情况:
Fixed:生成绝对定位的元素,相对于浏览器窗口进行定位,明显这样的定位的父元素就的文档了,也就没有父元素的相对点,但实际上我们根据盒子模型来算的话,实际上的定位出了left还有一个margin是会影响结果的,所以真实的定位值。

Left = ele.offset().left  –jQuery.css(elem, " marginLeft ", true)Top = ele.offset().top –jQuery.css(elem, " marginTop", true)

问题:为什么减去自身的margin值?

这样的算法才是精确的。
如果元素采用了Static、absolute、relative属性,那么都是跟定位有关系,都有父级的相对点,这样我们可以通过获取元素的offsetParent得到最近的父元素。这样的算法就比较简单了,我们可以获取元素相对文档的最真实的坐标减去父节点相对文档的坐标,这里涉及了2个元素的盒子模型所以都需要加上影响的属性。父节点的精确值要加上border的处理。

parentOffset.top += jQuery.css(offsetParent[0], "borderTopWidth", true);parentOffset.left += jQuery.css(offsetParent[0], "borderLeftWidth", true);

所以最终的计算公式:

top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true),left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true)
获取位置<!doctype html><html><head>  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>  <style type="text/css">    div { padding: 15px;width: 200px;}    p { margin:50px;}  </style>  <script src="http://code.jquery.com/jquery-latest.js"></script>  <title>position</title></head><body><div style="position:static;left:50px;top:50px;border:20px solid #ccc">  <p id="aaron" style="position:static;left:30px;top:110px;border:25px solid red">Hello</p></div><ul></ul><script type="text/javascript">  var p = $("#aaron");  var position = p.position();  var offset = p.offset();  $('ul').append('<li>p元素position坐标: left:'+ position.left +' top:'+ position.top +';</li>\n<li>p元素offset坐标: left:'+ offset.left +' top:'+ offset.top +';</li>')</script></body></html>