当浏览器在窗口中渲染HTML文档时,它会创建文档的一个视觉表示,其中每个元素都有自己的位置和大小。有时候我们需要某个元素精确的几何位置,比如,要使用CSS动态把一个元素定位到某个常规定位的元素旁边,必须要先知道这个常规定位元素的位置。
也就意味着我们需要在基于树的抽象文档模型和基于几何坐标系的文档视图之间切换。
文档坐标与视口坐标
文档元素的位置以CSS像素度量,其中x坐标向右表示增大,y坐标向下表示增大。有两个点可以作为坐标系的原点:文档的左上角和显示文档视口(viewport)的左上角。在顶级窗口和标签页中,"视口"就是浏览器窗口中实际显示文档内容的区域。
如果文档比视口小,比如浏览器窗口可以完整的显示所有文档内容,或者文档没有被滚动过,那么文档左上角就位于视口左上角。但通常情况下,要实现两种坐标系的转换们都必须加上或减去滚动位移。
滚动
Element.scroll()
方法 接收一个点的x和y坐标(文档坐标),并据以设置滚动条的位置。
当我们用window
去调用时,那就是浏览器窗口的滚动条进行滚动。
xml
<br>......<br> // <br>*100
<script>
window.scrollTo(200, 200);
</script>
当我们使用元素去调用这个方法时,就是元素本身的滚动条进行滚动,比如<textarea>
。
xml
<textarea name="" id="" cols="30" rows="10">
helloworld
// helloworld*100
helloworld
</textarea>
<script>
var oArea = document.getElementsByTagName('textarea')[0];
oArea.scrollTo(200, 200);
</script>
如果一个元素没有滚动条,那我们需要给它设置overflow: scroll;
,然后调用这个方法。
css
div{
width: 100px;
height: 100px;
border: 1px solid red;
overflow: scroll;
}
xml
<div>
helloworld
helloworld
helloworld
helloworld
helloworld
helloworld
</div>
<script>
var oDiv = document.getElementsByTagName('div')[0];
oDiv.scrollTo(50, 50);
</script>
Element.scrollBy()
方法 和scrollTo()
类似,但是它的参数是个相对值,会加在当前滚动位置上。
所以我们可以使用定时器实现自动滚动的效果。
javascript
setInterval(function(){
window.scrollBy(100, 100);
}, 1000);
视口尺寸
前面说过,浏览器窗口和一些HTML元素可以显示滚动的内容。我们有时候需要知道视口大小、内容大小和视口中内容的滚动位移。
对于浏览器而言,视口大小可以通过window.innerWidth/innerHeight
属性获得。
window.innerWidth/innerHeight
属性 获得浏览器窗口的水平/垂直尺寸(IE9
的一些版本/IE8
及以下不兼容)。
IE9
/IE8
及以下的写法如下,以下两种方法组合在一起可以解决IE浏览器中的兼容性问题,涉及怪异模式和标准模式。
- 标准模式:
document.documentElement.clientWidth/clientHeight
- 怪异模式:
document.body.clientWidth/clientHeigh
所以我们可以对以上方法进行封装,解决兼容性问题。
javascript
// 获取可是窗口的尺寸
function getViewportSize(){
console.log(document.compatMode);
if(false && window.innerWidth){
return {
width: window.innerWidth,
height: window.innerHeight
}
}else{
if(document.compatMode === 'BackCompat'){
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
}else{
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
}
文档尺寸与滚动
文档尺寸
document.documentElement.offsetwidth/offsetHeight
属性 返回文档的宽度与高度,这个值是包含滚动区域的。
针对兼容性问题,有时也需要使用document.body.scrollWidth/Height
属性。
javascript
// 获取整个文档的尺寸
function getScrollSize(){
if(document.body.scrollWidth){
return {
width: document.body.scrollWidth,
height: document.body.scrollHeight
}
}else{
return {
width: document.documentElement.scrollWidth,
height: document.documentElement.scrollHeight
}
}
}
文档滚动
当我们要获取文档的滚动距离时,看的不是滚动条的物理移动距离,而是要看页面移动的距离。因为考虑到可用性,滚动条的物理移动距离是按比例缩放。
window.pageXOffset/pageYoffset
属性 获得页面移动的水平/垂直距离(IE9
的一些版本/IE8
及以下不兼容)。
xml
<div style="height: 400px; border: 1px solid #000"></div>
<button>点击</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<script>
var oBtn = document.getElementsByTagName('button')[0];
oBtn.onclick = function(){
window.scrollTo(0, 400);
console.log(window.pageYOffset); // 400
}
</script>
下面这张表是关于浏览器版本的兼容性的整理。
所以IE9
的一些版本/IE8
及以下版本的写法如下,以下两种方法组合在一起可以解决IE浏览器中的兼容性问题,涉及怪异模式和标准模式。
- 标准模式:
document.documentElement.scrollLeft/scrollTop
- 怪异模式:
document.body.scrollLfet/scrollTop
所以我们可以对以上方法进行封装,解决兼容性问题。
javascript
// 获取滚动距离
function getScrollOffset(){
if(window.pageXOffset){
return {
// 常规写法
left: window.pageXOffset,
top: window.pageYOffset
}
}else{
return {
// IE浏览器的写法
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
还有一种不常见的写法window.scrollX/scrollY
属性。等同于 window.pageXOffset/pageYoffset
。
为了跨浏览器兼容性,请使用 window.pageXOffset/pageYoffset
。
元素尺寸、坐标与滚动
对于元素来说,它的尺寸和滚动要稍微复杂一点,多了一些属性。
元素尺寸
Element.offsetWidth/offsetHeight
属性 返回指定元素可见宽度/高度,包含元素的内边距和边框。
Element.clientWidth/clientHeight
属性 和offsetWidth/offsetHeight
类似,但是不包含元素的边框。
Element.scrollWidth/scrollHeight
属性 返回指定元素的内容区大小加上元素的内边距,再加上溢出内容的大小。在内容区没有溢出时,该属性等同于Element.clientWidth/clientHeight
。
css
div{
width: 500px;
height: 500px;
background-color: antiquewhite;
border: 1px solid #000;
}
xml
<div>
</div>
<script>
var oDiv = document.getElementsByTagName('div')[0];
console.log(oDiv.offsetHeight); // 502
console.log(oDiv.clientHeight); // 500
console.log(oDiv.scrollHeight); // 500
</script>
元素坐标
Element.offsetLeft/offsetTop
属性 返回指定元素相对于文档或定位父元素的水平/垂直偏移量(元素的x和y坐标)。
Element.offsetParent
属性 返回指定元素的定位父元素。
css
div{
width: 500px;
height: 500px;
margin-top: 200px;
margin-left: 200px;
background-color: antiquewhite;
border: 1px solid #000;
}
xml
<div>
</div>
<script>
var oDiv = document.getElementsByTagName('div')[0];
console.log(oDiv.offsetTop); // 200
console.log(oDiv.offsetLeft); // 208
</script>
元素滚动
Element.scrollLeft/scrollTop
属性 可以读取或设置元素滚动条的水平/垂直偏移量。
当滚动条滚到底时,满足等式 Element.offsetHeight = Element.scrollHeight - Element.scrollTop
。
在多数浏览器中,Element
对象也跟window
对象一样有scrollTo()
方法和scrollBy()
方法,但并非所有浏览器都支持。