视口坐标是相对于窗口的坐标,而文档坐标是相对于整个文档而言。例如,在文档坐标中如果一个元素的相对于文档的 Y 坐标是 200px,并且用户已经把浏览器向下滚动了 75px,那么视口坐标中元素的 Y 坐标为 200px – 75px = 125px。
如何获取浏览器滚动条的位置?Window 对象的 pageXOffset 和 pageYOffset 属性在所有浏览器中提供这些值,除 IE8 以及更早的版本。IE 和所有现代浏览器也可以通过 scrollLeft 和 scrollTop 属性获取滚动条位置。
下面代码的 getScrollOffsets 方法获取滚动条位置:
- //以一个对象的x和y属性放回滚动条的位置
- function getScrollOffsets(w) {
- w = w || window;
- //除了IE 8以及更早的版本以外,其他浏览器都支持
- if (w.pageXOffset != null) return {
- x: w.pageXOffset,
- y: w.pageYOffset
- };
- //对标准模式下的IE
- 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
- };
- }
有时候能够判定视口的尺寸也是非常有用的,下面的代码简便地查询视口尺寸:
- //作为一个对象的w和h属性返回视口的尺寸
- 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。 scrollLeft 和 scrollTop 获取滚动条位置,而 clientWidth 和 clientHeight 获取对象的尺寸。
判定一个元素的尺寸和位置最简单的方法是调用它的 getBoundingClientRect() 方法。该方法是在 IE5 中引入的,而现在当前的所有浏览器都实现了。它不需要参数,返回 left、right、top、bottom 属性的对象。
这个方法返回元素在视口坐标中的位置。为了转换为甚至用户滚动浏览器窗口以后任然有效的文档坐标,需要加上滚动偏移量:
- //元素相对于文档的坐标位置
- function getElementRect(e) {
- var box = e.getBoundingClientRect();
- var offsets = getScrollOffsets();
- var x = box.left + offsets.x;
- var y = box.top + offsets.y;
- return {
- x: x,
- y: y
- };
- }
在很多浏览器中,getBoundingClientRect() 返回的对象还包括 width 和 height 属性。但在原始的 IE 中未实现。可以这样计算元素的 width 和 height:
- //元素尺寸
- function getElementSize(e) {
- var box = getElementRect(e);
- var w = box.width || box.right - box.left;
- var h = box.height || box.bottom - box.top;
- return {
- w: w,
- h: h
- };
- }
之前的 getScrollOffsets 方法可以查询滚动条的位置。该例子的 scrollLeft 和 scrollTop 属性可以用来设置让浏览器滚动,但有一种更简单的方法从 Javascript 最早时期开始支持的。Window 对象的 scrollTop() 方法接口一个点的 X 和 Y 坐标(文档坐标),并作为滚动条的偏移量设置它们。下面代码滚动浏览器到文档最下面的页面可见:
- //滚动到浏览器最底部
- function scrollToBottom() {
- //获取文档和视口的高度
- var documentHeight = document.documentElement.offsetHeight;
- var viewportHeight = window.innerHeight; //或使用上面的getViewPortSize()方法
- //然后,滚动让最后一页在视口中可见
- window.scrollTo(0, documentHeight - viewportHeight);
- }
Window 的 scrollBy 方法和 scroll() 和 scrollTo() 类似,但是它的参数是相对的,并在当前滚动条的偏移量上增加。例如,快速阅读者可能会喜欢这样:
- javascript: void setInterval(function() {
- scrollBy(0, 10)
- },
- 200);
如果想让某个元素在文档中可见,可以利用 getBoundingClientRect() 计算元素的位置,并转换为文档坐标,然后使用 scrollTo() 方法达到目的。但在需要显示 html 元素上调用 scrollIntoView() 方法更方便。
scrollIntoView() 的行为与设置 window.location.hash 为一个命名锚点的名字后浏览器产生的行为类似。
任何 HTML 元素的只读属性 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 函数也不总是计算正确的值,下面看如何修复它。除了这些名字以 offset 开头的属性以外,所有的文档元素定义了其他两组属性,名字一组以 client 开头,另一组以 scroll 开头。即每个元素都有以下这些属性:
offsetWidth |
clientWidth | scrollWidth |
offsetHeight | clientHeight | crollHeight |
offsetLeft | clientLeft | scrollLeft |
offsetTop | clientTop | scrollTop |
offsetParent |
为了理解 client 和 scroll 属性,你需要知道元素的实际内容可能比分配用来容纳的盒子更大,因此单个元素可能有滚动条。内容区域是视口,就像浏览器窗口,当实际内容比视口大,需要把元素滚动套位置考虑进去。
clientWidth 和 clientHeight 类似 offsetWidth 和 offsetHeight,区别在于它们不包含边框大小。只包含内容和内边距。同时,如果浏览器在内边距和边框之间添加了滚动条,clientWidth 和 clientHeight 不包含滚动条尺寸。在文档的根元素上查询这些属性时,它们的返回值和窗口的 innerWidth 和 innerHeight 属性值相等。
clientLeft 和 clientTop 属性没什么用:它们返回元素的内边距的外边框和它的边框的外边缘之间的水平距离和垂直距离。
scrollWidth 和 scrollHeight 是元素的内容区域加上它的内边距再加上任何溢出内容的尺寸。当内容正好和内容区域匹配没溢出时,这些属性与 clientWidth 和 clientHeight 相等。有溢出时,包含了溢出的内容尺寸。
scollLeft 和 scrollTop 指定元素滚动条的位置。在 getScrollOffsets() 方法中查询过它们。注意,scrollLeft 和 scrollTop 是可写的,通过设置它们来让元素中的内容滚动(HTML 元素并没有类似 Window 对象的 scrollTo()方法。
下面代码介绍了前面几个函数的使用:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- <script type="text/javascript">
- //以一个对象的x和y属性放回滚动条的位置
- function getScrollOffsets(w) {
- w = w || window;
- //除了IE 8以及更早的版本以外,其他浏览器都支持
- if (w.pageXOffset != null) return {
- x: w.pageXOffset,
- y: w.pageYOffset
- };
- //对标准模式下的IE
- 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
- };
- }
- //作为一个对象的w和h属性返回视口的尺寸
- 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
- };
- }
- //元素相对于文档的坐标位置
- function getElementRect(e) {
- var box = e.getBoundingClientRect();
- var offsets = getScrollOffsets();
- var x = box.left + offsets.x;
- var y = box.top + offsets.y;
- return {
- x: x,
- y: y
- };
- }
- //元素尺寸
- function getElementSize(e) {
- var box = getElementRect(e);
- var w = box.width || box.right - box.left;
- var h = box.height || box.bottom - box.top;
- return {
- w: w,
- h: h
- };
- }
- //滚动到浏览器最底部
- function scrollToBottom() {
- //获取文档和视口的高度
- var documentHeight = document.documentElement.offsetHeight;
- var viewportHeight = window.innerHeight; //或使用上面的getViewPortSize()方法
- //然后,滚动让最后一页在视口中可见
- window.scrollTo(0, documentHeight - viewportHeight);
- }
- //计算元素位置
- 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
- };
- }
- </script>
- </head>
- <body>
- <button id="scrolltoBottomBtn">
- 滚动到浏览器
- </button>
- <div style="height: 400px; background: red;">
- </div>
- <button id="btn">
- 获取滚动条位置
- </button>
- <button id="viewportBtn">
- 获取视口尺寸
- </button>
- <button id="eleRectBtn">
- 元素文档坐标
- </button>
- <script type="text/javascript">
- var btn = document.getElementById("btn");
- btn.onclick = function(event) {
- console.log(getScrollOffsets());
- }
- var viewportBtn = document.getElementById("viewportBtn");
- viewportBtn.onclick = function(event) {
- console.log(getViewportSize());
- }
- var eleRectBtn = document.getElementById("eleRectBtn");
- eleRectBtn.onclick = function(eevent) {
- console.log(getElementRect(this));
- }
- var scrolltoBottomBtn = document.getElementById("scrolltoBottomBtn");
- scrolltoBottomBtn.onclick = function() {
- scrollToBottom();
- }
- </script>
- </body>
- </html>
如果本篇内容对大家有帮助,请点击页面右下角的关注。如果觉得不好,也欢迎拍砖。你们的评价就是博主的动力!下篇内容,敬请期待!
来源: http://www.cnblogs.com/w-wanglei/p/5863240.html