元素的位置
获取元素的位置
Element接口提供了众多属性用于获取元素的各种位置(单位像素),这些属性通常为只读,并且只有元素已经在DOM树中且CSS属性的display不为none时才有效。
偏移位置
偏移位置指的是元素相对于其父级元素的当前位置。
- Element.offsetTop
元素的左上角与父容器(offsetParent对象)左上角的垂直距离 - Element.offsetLeft
元素的左上角与父容器(offsetParent对象)左上角的水平距离
定位级的父级元素并不等同于于文档结构中的父级元素(Node.parentElement),通过Element.offsetParent属性获取。
元素的offsetParent的计算遵从下面的算法:
- 没有关联一个CSS布局框的元素,其offsetParent是null
- 根元素,其offsetParent是null
- BODY元素,其offsetParent是null
- position为fixed的元素,其offsetParent是null(有些浏览器返回body),实际上是body
- AREA元素,且其某个祖先元素是MAP元素,其offsetParent为其最近的MAP祖先元素
- position为absolute, relative的元素,其offsetParent总是为DOM树中距其最近的已定位的祖先元素
- position为static的元素,如果在表格内, 其offsetParent为其最近的TD、TH 或 TABLE元素,如果不在表格内,其offsetParent为DOM树中距其最近的已定位的祖先元素。
备注:
- 已定位的祖先元素: position不为static的元素
绝对位置
绝对位置指的是元素在文档页面中的位置,即相对于文档左上原点的当前位置。
每个元素都有offsetTop和offsetLeft属性,表示该元素的左上角与父容器(offsetParent对象)左上角的距离。所以,只需要将这两个值进行累加,就可以得到该元素的绝对坐标。
function getPagePosition(el){ var left = el.offsetLeft, top = el.offsetTop, p = el.offsetParent; while (p !== null){ left += p.offsetLeft; top += p.offsetTop; p = p.offsetParent; } return { "top" : top, "left": left }; }
另外,使用getBoundingClientRect()方法可以快速的获取元素的绝对位置
function getPagePosition(el){ var obj = el.getBoundingClientRect(); return { "left": obj.left + window.pageXOffset, "top": obj.top + window.pageYOffset } }
相对位置
网页元素的相对位置,指该元素左上角相对于浏览器窗口左上角的坐标。
function getViewportPosition(el){ var pagePos= getPagePosition(el); return { "left": pagePos.left - window.pageXOffset, "top": pagePos.top - window.pageYOffset } }
另外,使用getBoundingClientRect()方法可以快速的获取元素的绝对位置
function getViewportPosition(el){ var obj = el.getBoundingClientRect(); return { "left": obj.left, "top": obj.top } }
工具函数列表
uDOMlib所提供的工具函数之中,有一部分与元素位置相关,下面列出部分函数的源代码实现以供参考。
position()
返回或设定相对于定位父元素左上角的位置。 如果只处理水平或垂直位置的话可调用left()或top()方法。
position : function(node,coords) { if (value == undefined) { var // Get *real* offsetParent offsetParent = this.offsetParent(node), // Get correct offsets offset = this.boundingPosition(node), parentOffset = this.boundingPosition(offsetParent), mex = this.marginExtents(node), pbex = this.borderExtents(offsetParent); // Subtract parent offsets and element margins return { top: offset.top - pbex.top - mex.top, left: offset.left - pbex.left - mex.left } } else { var props = { top: coords.top, left: coords.left } if (styler.css(node,"position") == "static") { props['position'] = "relative"; } styler.css(props); return this; } },
boundingPosition()
返回或设定相对于视口左上原点的位置
boundingPosition : function(node,coords) { if (coords === undefined) { return rootNodeRE.test(node.nodeName) ? { top: 0, left: 0 } : node.getBoundingClientRect(); } else { var // Get *real* offsetParent offsetParent = this.offsetParent(node), // Get correct offsets parentOffset = this.boundingPosition(offsetParent), mex = this.marginExtents(node), pbex = this.borderExtents(offsetParent); this.position(node,{ top: coords.top - parentOffset.top - mex.top - pbex.top, left: coords.left - parentOffset.left - mex.left - pbex.left }); return this; } }
pagePosition()
返回或设定相对于页面左上原点的位置
pagePosition: function(node,coords) { if (coords === undefined) { var obj = node.getBoundingClientRect() return { left: obj.left + window.pageXOffset, top: obj.top + window.pageYOffset } } else { var // Get *real* offsetParent offsetParent = this.offsetParent(node), // Get correct offsets parentOffset = this.pagePosition(offsetParent), mex = this.marginExtents(node), pbex = this.borderExtents(offsetParent); this.position(node,{ top: coords.top - parentOffset.top - mex.top - pbex.top, left: coords.left - parentOffset.left - mex.left - pbex.left }); return this; } }
offsetParent()
返回元素定位上的父元素。 offsetParent()内部调用了Element.offsetParent属性,并作了一定的封装处理,以保证返回的父元素一定是已定位元素(position不是static)。 以下是函数的实现代码
function offsetParent(node) { var parent = node.offsetParent || document.body; while (parent) { if (!rootNodeRE.test(parent.nodeName) { break; } if (getComputedStyle(parent).position != "static")) { break; } parent = parent.offsetParent; } return parent; }
scrollLeft
返回或设置元素的滚动条的水平位置。滚动条的水平位置指的是从其左侧滚动过的像素数。当滚动条位于最左侧时,位置是 0。
scrollLeft: function(node,value) { var hasScrollLeft = "scrollLeft" in node; if (value === undefined) { return hasScrollLeft ? node.scrollLeft : node.pageXOffset } else { if (hasScrollLeft){ node.scrollLeft = value; } else { node.scrollTo(value,node.scrollY); } return this; } }
scrollTop
返回或设置元素的滚动条的垂直位置。滚动条的垂直位置指的是从其上侧滚动过的像素数。当滚动条位于最上侧时,位置是 0。
scrollTop: function(node,value) { var hasScrollTop = "scrollTop" in node; if (value === undefined) { return hasScrollTop ? node.scrollTop : node.pageYOffset } else { if (hasScrollTop) { node.scrollTop = value; } else { node.scrollTo(node.scrollX, value); } return this; } }