JS | JS之深入理解滚动大小scroll系列属性

前面两篇博文分别介绍过偏移大小客户区大小。本文介绍元素尺寸中内容最多的一部分——滚动scroll。

一、滚动大小

滚动宽高

参考:Javascript进阶篇——获取浏览器窗口可视区域大小 + 获取网页尺寸 - 博客园

scrollHeight

scrollHeight表示元素的总高度,包括由于溢出而无法展示在网页的不可见部分

scrollWidth

scrollWidth表示元素的总宽度,包括由于溢出而无法展示在网页的不可见部分

注意:IE7-浏览器返回值是不准确的

【1】没有滚动条时,scrollHeight与clientHeight属性结果相等,scrollWidth与clientWidth属性结果相等

<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;"></div>
<script>
//120 120
console.log(test.scrollHeight,test.scrollWidth);
//120 120
console.log(test.clientHeight,test.clientWidth);
</script>

【2】存在滚动条时,但元素设置宽高大于等于元素内容宽高时,scroll和client属性的结果相等 

<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:1;">
    内容<br>内容<br>
</div>
<script>
//103(120-17) 103(120-17)
console.log(test.scrollHeight,test.scrollWidth);
//103(120-17) 103(120-17)
console.log(test.clientHeight,test.clientWidth);
</script>

【3】存在滚动条,但元素设置宽高小于元素内容宽高,即存在内容溢出的情况时,scroll属性大于client属性

注意:scrollHeight属性存在兼容性问题,chrome和safari浏览器中,scrollHeight包含padding-bottom;而IE和firefox不包含padding-bottom

<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;">
    内容</div>
<script>
//chrome/safari:220(200+10+10)
//firefox/IE:210(200+10)
console.log(test.scrollHeight);
//103(120-17)
console.log(test.clientHeight);
</script>

页面尺寸

document.documentElement.clientHeight表示页面的可视区域的尺寸,而document.documentElement.scrollHeight表示html元素内容的实际尺寸。但是由于各个浏览器表现不一样,分为以下几种情况

【1】html元素没有滚动条时,IE和firefox的client和scroll属性始终相同,且返回可视区的尺寸大小;而safari和chrome表现正常,clientHeight返回可视区域大小,而scrollHeight返回元素内容大小

//firefox:  755 755
//chrome:   947 8(body元素的margin)
//safari:   744 8(body元素的margin)
//IE:       768 768
console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight)

【2】html元素存在滚动条时,各个浏览器都表现正常。clientHeight返回可视区域大小,而scrollHeight返回元素内容大小 

<body style="height:1000px">
<script>
//firefox:  755 1016(1000+8*2)
//chrome:   947 1016(1000+8*2)
//safari:   744 1016(1000+8*2)
//IE:       768 1016(1000+8*2)
console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight)
</script>

兼容

因此,要取得文档实际高度时,要取得<html>元素的scrollHeight和clientHeight的最大值

var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);
var docWidth  = Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);

滚动长度

scrollTop

scrollTop属性表示被隐藏在内容区域上方的像素数。元素未滚动时,scrollTop的值为0,如果元素被垂直滚动了,scrollTop的值大于0,且表示元素上方不可见内容的像素宽度

scrollLeft

scrollLeft属性表示被隐藏在内容区域左侧的像素数。元素未滚动时,scrollLeft的值为0,如果元素被水平滚动了,scrollLeft的值大于0,且表示元素左侧不可见内容的像素宽度

当滚动条滚动到内容底部时,符合以下等式

scrollHeight == scrollTop  + clientHeight
<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;">
    内容</div>
<button id='btn1'>点击</button>
<div id="result"></div>
<script>
btn1.onclick = function(){
    result.innerHTML = 'scrollTop:' + test.scrollTop+';clientHeight:' + test.clientHeight + ';scrollHeight:' + test.scrollHeight
}
</script>

与scrollHeight和scrollWidth属性不同的是,scrollLeft和scrollTop是可写的

注意:为scrollLeft和scrollTop赋值为负值时,并不会报错,而是静默失败

<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;">
    内容</div>
<button id='btn1'>向下滚动</button>
<button id='btn2'>向上滚动</button>
<script>
btn1.onclick = function(){test.scrollTop += 10;}
btn2.onclick = function(){test.scrollTop -= 10;}
</script>

 番外:网页卷去的距离与偏移量

scrollLeft: 设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离 ,即左边灰色的内容。

scrollTop: 设置或获取位于对象最顶端与窗口中可见内容的最顶端之间的距离 ,即上边灰色的内容。

offsetLeft: 获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置 。

offsetTop: 获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算顶端位置 。

offsetParent:布局中设置postion属性(Relative、Absolute、fixed)的父容器,从最近的父节点开始,一层层向上找,直到HTML的body。 

例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title></title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script>
      function req() {
        var div = document.getElementById("div1");
        document.getElementById("li1").innerHTML = div.offsetTop + "px"; //div1距离屏幕顶部的距离
        document.getElementById("li2").innerHTML = div.offsetLeft + "px"; //div1距离屏幕左部的距离
        document.getElementById("li3").innerHTML = div.scrollTop + "px"; //div1纵向滚动条滚动的距离
        document.getElementById("li4").innerHTML = div.scrollLeft + "px"; //div1横向滚动条滚动的距离
      }
    </script>
  </head>
  <body style="border: 10px solid #ccc; padding: 0px 0px; margin: 5px 10px">
    <div style="width: 60%; border-right: 1px dashed red; float: left">
      <div style="float: left">
        <div
          id="div1" style=" border: 5px red solid;height: 300px;width: 200px;overflow: auto;">
          <div style="height: 500px; width: 400px">
            请调整横竖滚动条后,点击按钮后查看offsetTop、offsetLeft、scrollTop、scrollLeft值。
          </div>
        </div>
        <input
          type="button"
          value="点击我!"
          onclick="req()"
          style="border: 1px solid purple; height: 25px"
        />
      </div>
    </div>
    <div style="width: 30%; float: left">
      <ul style="list-style-type: none; line-height: 30px">
        结果:
        <li>offsetTop : <span id="li1"></span></li>
        <li>offsetLeft : <span id="li2"></span></li>
        <li>scrollTop : <span id="li3"></span></li>
        <li>scrollLeft : <span id="li4"></span></li>
      </ul>
    </div>
    <div style="clear: both"></div>
  </body>
</html>

二、页面滚动

理论上,通过document.documentElement.scrollTop和scrollLeft可以反映和控制页面的滚动;但是chrome和safari浏览器是通过document.body.scrollTop和scrollLeft来控制的

<body style="height:1000px">
  <button id='btn1' style="position:fixed;top:0;">点击</button>
  <div id="result" style="position:fixed;top:30px;"></div>
  <script>
    btn1.onclick = function () {
      result.innerHTML = 'html的scrollTop:' + document.documentElement.scrollTop + ';body的scrollTop:' + document.body.scrollTop;
    }
  </script>
</body>

 所以,页面的滚动高度兼容的写法,如下:

var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop

回到顶部

可以利用scrollTop来实现回到顶部的功能

function scrollTop() {
  if ((document.body.scrollTop || document.documentElement.scrollTop) != 0) {
    document.body.scrollTop = document.documentElement.scrollTop = 0;
  }
}
<body style="height: 1000px">
  <button id="btn" style="position: fixed">回到顶部</button>
  <script>
    function scrollTop() {
      if (
        (document.body.scrollTop || document.documentElement.scrollTop) != 0
      ) {
        document.body.scrollTop = document.documentElement.scrollTop = 0;
      }
    }
    btn.onclick = scrollTop;
  </script>
</body>

演示效果:

参考:回到顶部的5种方法及对回到顶部的功能进行增强的方式: 回到顶部 - 小火柴的前端小册子 - 开发文档 - 文江博客

还有两个window的只读属性可以获取整个页面滚动的像素值,它们是pageXOffsetpageYOffset

pageXOffset

pageXOffset表示水平方向上页面滚动的像素值

pageYOffset

pageYOffset表示垂直方向上页面滚动的像素值

注意:IE8-浏览器不支持pageXOffset 和 pageYOffset

<body style="height: 1000px">
  <button id="btn1" style="position: fixed; top: 0">点击</button>
  <div id="result" style="position: fixed; top: 30px"></div>
  <script>
    btn1.onclick = function () {
      result.innerHTML = "pageYOffset:" + window.pageYOffset;
    };
  </script>
</body>

演示效果如下:

三、滚动方法

scrollTo(x,y)

scrollTo(x,y) 方法滚动当前window中显示的文档,让文档中由坐标x和y指定的点位于显示区域的左上角

<body style="height: 1000px">
  <button id="btn" style="position: fixed">滚动</button>
  <script>
    btn.onclick = function () {
      scrollTo(0, 0);
    };
  </script>
</body>

 演示效果如下:

scrollBy(x,y)

scrollBy(x,y) 方法滚动当前window中显示的文档,x和y指定滚动的相对量

​<body style="height:1000px">
  <button id='btn1' style="position:fixed">向下滚动</button>
  <button id='btn2' style="position:fixed;top:40px">向上滚动</button>
  <script>
  btn1.onclick = function(){scrollBy(0,100);}
  btn2.onclick = function(){scrollBy(0,-100);}
  </script>
</body>

演示效果如下:

【小应用】

利用scrollBy()加setInterval计时器实现简单的快速滚动功能

<body style="height:1000px">
  <button id='btn1' style="position:fixed">开始滚动</button>
  <button id='btn2' style="position:fixed;top:40px">停止滚动</button>
  <script>
    var timer = 0;
    btn1.onclick = function () {
      timer = setInterval(function () {
        scrollBy(0, 10);
      }, 100)
    }
    btn2.onclick = function () {
      clearInterval(timer);
      timer = 0;
    }
  </script>
</body>

演示效果如下:

scrollIntoView()

Element.scrollIntoView() 方法滚动当前元素,进入浏览器的可见区域

该方法可以接受一个布尔值作为参数。如果为true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);如果为false,表示元素的底部与当前区域的可见部分的尾部对齐(前提是当前区域可滚动)。如果没有提供该参数,默认为true

<body style="height:1000px">
  <div id="test" style="height:100px;width:100px;position:absolute;left:0;top:500px;background-color:green"></div>
  <button id='btn1' style="position:fixed">滚动到页面开头</button>
  <button id='btn2' style="position:fixed;top:40px">滚动到页面结尾</button>
  <script>
    btn1.onclick = function () {
      test.scrollIntoView();
    };
    btn2.onclick = function () {
      test.scrollIntoView(false);
    }
  </script>
</body>

演示效果如下:

scrollIntoViewIfNeeded()

scrollIntoViewIfNeeded(true) 方法只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。

如果将可选的alignCenter参数设置为true,则表示尽量将元素显示在视口中部(垂直方向)

注意:方法只有chrome和safari支持

<body style="height:1000px">
  <div id="test" style="height:100px;width:100px;position:absolute;left:0;top:500px;background-color:green"></div>
  <button id='btn' style="position:fixed">滚动到页面中间</button>
  <script>
  btn.onclick = function(){
      test.scrollIntoViewIfNeeded(true)
  };
  </script>
</body>

演示效果如下:

scrollByLines(lineCount)

scrollByLines(lineCount)方法将元素的内容滚动指定的行高,lineCount值可以是正值, 也可以是负值。

注意:该方法只有safari支持

<body>
  <div id="test"
    style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;">
    内容</div>
  <button id='btn1'>向下滚动</button>
  <button id='btn2'>向上滚动</button>
  <script>
    btn1.onclick = function () {
      test.scrollByLines(1);
    };
    btn2.onclick = function () {
      test.scrollByLin(-1);
    };
  </script>
</body>

scrollByPages(pageCount)

scrollByPages(pageCount)方法将元素的内容滚动指定的页面高度,具体高度由元素的高度决定

注意:该方法只有safari支持

<body>
  <div id="test"
    style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;">
    内容</div>
  <button id='btn1'>向下滚动</button>
  <button id='btn2'>向上滚动</button>
  <script>
    btn1.onclick = function () { test.scrollByPages(1); }
    btn2.onclick = function () { test.scrollByPages(-1); }
  </script>
</body>

四、滚动事件

scroll事件是在window对象上发生的,它表示的是页面中相应元素的变化。当然,scroll事件也可以用在有滚动条的元素上。| 番外:CSS滚动条 - 小火柴的蓝色理想 - 博客园


<body style="height:1000px">
  <div id="result" style="position:fixed;top:10px;"></div>
  <script>
    window.onscroll = function () {
      result.innerHTML = '页面的scrollTop:' + (document.documentElement.scrollTop || document.body.scrollTop);
    }
  </script>
</body>

演示效果如下:


 ● 参考资料 ●

scrollTop及offsetTop的对比_scrolltop和offsettop-CSDN博客

JS | JS之元素偏移量 offset 系列属性详解 - 烤地瓜的CSDN博客

JS | JS之深入理解客户区尺寸client系列属性 - 烤地瓜的CSDN博客

JS | 图片懒加载的6种实现方案之JS监听scroll滚动事件 - 烤地瓜的CSDN博客

猜你喜欢

转载自blog.csdn.net/sunyctf/article/details/143031317