【js学习笔记----------文档和元素的几何形状和滚动】
文档坐标和视口坐标
元素的位置以像素位置来度量的,向右代表X坐标的增加,向下代表Y坐标的增加。但是,有两个不同的点作为坐标系的原点:元素的x和y坐标可以相对于文档的左上角或相对于在其中显示文档的视口左上角。在顶级窗口和标签页中,“视口”只是实际显示文档内容的浏览器的一部分:它不包括浏览器“外壳”(如菜单、工具条和标签页)。针对框架页中显示的文档,视口是定义了框架页的 <iframe>元素。无论在何种情况下,当讨论元素的位置时,必须弄清楚所有使用的坐标是文档坐标还是视口坐标(视口坐标有时也叫窗口坐标)。
如果文档比视口小,或者说它还未出现滚动,则文档的左上角就视口的左上角,文档和视口坐标系统是同一个。但是,一般来说,要在两种坐标系之间互相转换,必须加上或减去滚动的偏移量。例如:在文档坐标中如果一个元素的y坐标是200px,并且用户已经把浏览器向下滚动75像素,那么视口坐标中的元素y坐标是125px。
文档坐标比视口坐标更加基础,并且用户滚动时它们不会发生变化。不过客户端编程中使用视口坐标是非常常见的。当使用CSS指定元素的位置时运用了文档坐标。但是,最简单的查询元素位置的方法返回视口坐标中的位置。类似地,当为鼠标事件注册事件处理程序函数时,报告的鼠标指针坐标是在视口坐标系中的。
为了在坐标系之间互相转换,我们需要判定浏览器窗口的滚动条的位置。
pageXOffset和pageYOffset属性在所有浏览器中提供值(除IE8及更早版本)
IE及其它浏览器:也可以通过scrollLeft和scrollTop属性来获得滚动条位置。令人迷惑的是,正常情况下通过查询文档的根节点(document.documentElement)来获取这些属性值,但在怪异模式下,必须在文档的<body> 元素document.body上查询它们。
//查询窗口滚动条的位置
function getScrollOffsets(w){
w= w||window;
if(w.pageXOffset !=null) return {x:w.pageXOffset,y:w.pageYOffset};
var d = w.document;
if(document.compatMode==”CSS1Compat”)
return{x:d.documentElement.scrollLeft,y:d.documentElement.scrollTop};
//对怪异模式下的浏览器
return {x:d.body.scrollLeft,y:d.body.scrollTop};
}
//查询窗口的视口尺寸
function getViewportSize(w){
w = w||window;
//除IE8及更早的版本以外,其它的浏览器里
if(w.innerWidth!=null)return {w:w.innerWidth,h:w.innerHeight};
//标准模式下的IE
var d = w.document
if(document.compatMode==”CSS1Compat”)
return {
w:d.documentElement.clientWidth,
h:d.documentElement.clientHeight
};
//怪异模式
return {w:d.body.clientWidth,h:d.body.clientHeight};
}
上例中我们已经用到了scrollLeft、scrollTop、clientWidth和clientHeight
查询元素的几何尺寸
判定一个元素的尺寸和位置最简单的方法是调用它的getBoundingClientRect()方法(IE5中已经实现),它不需要参数,返回一个left,right,top,bottom属性对象。left和top属性表示元素的左上角x y坐标,right和bottom属性表示元素右下角的x y坐标。这个方法返回元素在视口坐标中的位置。为了转化为甚至用户滚动浏览器窗口以后仍然有效的文档坐标,需要加上滚动的偏移量:
var box =e.getBoundingClientRect()
var offsets = getScrollOffsets();
var x = box.left+offsets.x;
var y= box.top+offsets.y;
W3C浏览器中,getBoundingClientRect()返回的对象还包含width和height属性(原始IE没实现),
var box = e.getBoundingClientRect();
var w = box.width||(box.right-box.left);
var h = box.height||(box.bottom-box.top)
getBoundingClientRect()所返回的坐标包含边框和内边距,但不包含元素的外边距
如果一些被断成多行的内联元素,使用getBoundingClientRect获取的是一个包含多行的一个矩形。
可以使得getClientRects()方法来获得一个只读的类数组对象,它的每个元素类似于getBoundingClientRect()返回的矩形对象。这两个方法 不是实时的,只在是调用那一刻,文档视觉状态的静态快照,在用户滚动或改变浏览器窗口大小时不会更新它们。
判定元素在某点
getBoundingClientRect()方法使们们能在视口中判定元素的位置。但有时我们想反过来,判定在视口中的指定位置上有什么元素,这可以Document对象的elementFromPoint()方法来判定。传递x y坐标,该方法返回在指定位置的一个元素(最里面、最上面的元素)。
滚动
window对象的scrollTop()方法接受一个xy(文档坐标),并作为滚动条的偏移量设置它们。即窗口滚动到指定的点出现在视口的左上角,如果指定的点太接近于文档的下边缘或右边缘,浏览器将尽量保证它和视口左上角之间最近,
关于元素尺寸、位置和溢出的更多信息
offsetWidth属性
offsetHeight属性
以CSS像素返回它的屏幕尺寸。返回的尺寸包含元素的边框和内边距,除去外边距。
所有HTML元素拥有offsetLeft和offsetTop属性来返回元素的x和y坐标。对于很多元素,这些值是文档坐标,并直接指定元素位置。但对于已定准元素的后代元素和一些其它元素(如表格)这些属性返回的坐标是相对祖先元素的而非文档。
offsetParent属性指定这些属性所相对的父元素。如果offsetParent为null,这些属性都是文档坐标,因此,一般来说,用offsetLeft和offsetTop来计算元素e的位置需要一个循环:
function getElementPosition(e){
var x=0,y=0;
while(e!=null){
x+=e.offsetLeft;
y+=e.offsetTop;
e= e.offsetParent;
}
return {x:x,y:y};
}
以上计算的是指定元素在文档中的坐标。
尽管有这些方法,也不能对元素的位置一锤定音。因为getElementPosition()函数也不总是计算正确的值,下面看看如何时修复它:
所有文档元素定义了以下属性
offsetWidth | clientWidth | scrollWidth |
offsetHeight | clientHeight | scrollHeight |
offsetLeft | clientLeft | scrollLeft |
offsetTop | clientTop | scrollTop |
offsetParent |
|
|
html元素实际内容有可能比分配用来容纳内容的盒子更大,因此单个元素可能有滚动条。内容区域是视口,像浏览器窗口,当实际内容比视口更大时,需要把元素的滚动条位置考虑进去。
clientWidth和clientHeight类似offsetWidth和offsetHeight,不同的是它们不包含边框大小,只包含内容和它的内边距。注意,对于内联元素,clientWidth和clientHeight总是返回0;
clientLeft和clientTop属性没什么用:它们返回元素的内边距的外边缘和它的边框的外边缘之间的水平距离和垂直距离