本文详解JavaScript中元素位置的两种坐标系:文档坐标与视口坐标。重点讲解如何通过getBoundingClientRect()获取视口坐标,以及如何利用pageXOffset、scrollLeft等属性处理滚动偏移量以实现坐标转换。同时提供获取视口尺寸和滚动条位置的兼容代码,适用于IE8及以上现代浏览器及不同文档模式。
文档坐标与视口坐标的概念
元素的位置以像素为单位进行度量,向右移动对应X坐标增加,向下移动对应Y坐标增加。然而,存在两个不同的坐标系原点:元素的X和Y坐标可以相对于文档的左上角,也可以相对于当前在视口中显示文档部分的左上角。
在独立窗口和标签页中,“视口”仅指浏览器实际显示文档内容的区域,不包括浏览器的“外壳”部分,如菜单栏、工具栏和标签页栏。

对于在框架中显示的文档,视口由包含该文档的<iframe>元素定义。无论何种情况,在讨论元素位置时,必须明确使用的是文档坐标还是视口坐标(注意,视口坐标有时也称为窗口坐标)。
坐标转换与滚动偏移量处理
如果文档尺寸小于视口或未发生滚动,文档左上角与视口左上角重合,此时文档坐标与视口坐标系统一致。通常情况下,要在两种坐标系之间转换,需加上或减去滚动偏移量(scroll offset)。例如,若文档坐标中某元素Y坐标为200像素,且用户向下滚动75像素,则该元素在视口坐标中的Y坐标为125像素。同理,若视口坐标中某元素X坐标为400像素,且用户水平滚动200像素,则该元素在文档坐标中的X坐标为600像素。
文档坐标比视口坐标更基础,且在用户滚动时保持不变。但在客户端编程中,使用视口坐标非常常见。CSS定位元素时使用文档坐标,而查询元素位置最简单的方法是getBoundingClientRect(),它返回视口坐标中的位置。此外,注册鼠标事件处理程序时,报告的鼠标指针坐标也是基于视口坐标系。

获取滚动条位置的方法
为了实现坐标系转换,需要确定浏览器窗口的滚动条位置。Window对象的pageXOffset和pageYOffset属性在所有现代浏览器中提供这些值,但不包括IE8及更早版本。IE及所有现代浏览器也可通过scrollLeft和scrollTop属性获取滚动条位置。值得注意的是,正常情况下需通过查找文档根节点(document.documentElement)来获取这些属性,但在怪异模式下,必须在文档的<body>元素(document.body)上查询。以下代码展示了如何简便地查询滚动条位置。
functon getScrollOffsets(w){
w = w || window;
var sLeft,sTop;
if(w.pageXOffset != null) {
sLeft = w.pageXOffset;
sTop = w.pageYOffset;
return {x:sLeft,y:sTop};
}
if(document.compatMode == "CSS1Compat"){
sLeft = document.documentElement.scrollLeft == 0 ? document.body.scrollLeft : document.documentElement.scrollLeft;
sTop = document.documentElement.scrollTop == 0 ? document.body.scrollTop : document.documentElement.scrollTop;
return {x:sLeft,y:sTop};
}else if(document.compatMode == "BackCompat"){
sLeft = document.body.scrollLeft;
sTop = document.body.scrollTop;
return {x:sLeft,y:sTop};
}
}
有时判定视口尺寸非常有用,例如确定文档部分是否当前可见。利用滚动偏移量查询视口尺寸的简单方法在IE8及更早版本中无法工作,且该技术在IE中的运行方式还取决于浏览器处于怪异模式还是标准模式。
Window对象与DOM元素属性详解
Window对象下的相关属性包括:
innerHeight:包含滚动条在内的窗口内容部分的高度。
innerWidth:包含滚动条在内的窗口内容部分的宽度。
outerHeight:整个浏览器的高度,包括界面所有组成部分。
outerWidth:整个浏览器的宽度,包括界面所有组成部分。
pageXOffset:浏览器窗口滚动条X轴的位置。
pageYOffset:浏览器窗口滚动条Y轴的位置。
scrollX:浏览器窗口滚动条X轴的位置。
scrollY:浏览器窗口滚动条Y轴的位置。
其他相关属性定义如下:
document.documentElement 和 document.body 的相关属性: clientHeight:视口内可见内容的大小,不包括滚动部分和滚动条。 clientWidth:视口内可见内容的宽度。 clientLeft:元素左边框的宽度。 clientTop:元素上边框的高度。 offsetHeight:内容大小,包括滚动条。 offsetWidth:内容宽度,包括滚动条。 offsetLeft:元素左边框左侧到包含它的定位父级或body的距离。 offsetTop:元素上边框顶部到包含它的定位父级或body的距离。 scrollHeight:滚动内容的大小,包括滚动的部分,但不包括滚动条。 scrollWidth:滚动内容的宽度。 scrollTop:滚动条在Y轴上的偏移量。 scrollLeft:滚动条在X轴上的偏移量。
查询视口尺寸的实现代码
查询窗口视口尺寸的代码如下:
function getViewportSize(w){
w = w || window;
var cWidth,cHeight;
if(w.innerWidth != null){
cWidth = w.innerWidht;
cHeight = w.innerHeight;
return {w:cWidth,h:w.cHeight};
}
if(document.compatMode == "CSS1Compat"){
cWidth = document.documentElement.clientWidth;
cHeight = doument.documentElement.clientHeight;
return {w:cWidth,h:w.cHeight};
}else if(document.compatMode == "BackCompat"){
cWidth = document.body.clientWidth;
cHeight = doument.body.clientHeight;
return {w:cWidth,h:w.cHeight};
}
}
以上所述即为本文的全部内容,希望对大家有所帮助。