滚动事件和加载事件

2,863 阅读4分钟

滚动事件和加载事件

1.1 滚动事件

当页面进行滚动时触发的事件

很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部

事件名:scroll

监听整个页面滚动:

        // 页面级别滚动
        window.addEventListener('scroll', function(){
            // 执行的操作
            // 输出当前页面的滚动距离
            console.log(document.documentElement.scrollTop);
        })

演示

    <div>
        <h2>1</h2>
        <h2>2</h2>
			// 1 - 100 的输出演示
        <h2>98</h2>
        <h2>99</h2>
        <h2>100</h2>
    </div>
    <script>
        // 页面级别滚动
        window.addEventListener('scroll', function(){
            // console.log('滚蛋');
            // 这个代码可以回去到当前页面的滚动距离
            console.log(document.documentElement.scrollTop);
            
        })
        // const div = document.querySelector('div')
        // div.addEventListener('scroll', function(){
        //     console.log('又开始浪了');
        // })
    </script>

1.2 加载事件

加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

有些时候需要等页面资源全部处理完了做一些事情

老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到

事件名:load 监听页面所有资源加载完毕:

给 window 添加 load 事件

1649775303140

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载

事件名:DOMContentLoaded

监听页面DOM加载完毕:

给 document 添加 DOMContentLoaded 事件

1649775344375

页面加载区别

    <video
    controls
    src="https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/36/82/569828236/569828236-1-16.mp4?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1649906485&gen=playurlv2&os=cosbv&oi=2028708454&trid=926e1b0362e4450296eda32f1f091968h&platform=html5&upsig=de4859a796154f0ae2152c7a97789a6d&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=414874315&bvc=vod&nettype=0&bw=52793&logo=80000000"
  ></video>
  <script>
    /* 
    有很多业务和功能 都需要使用到外部资源(外部css js 图片 视频)
    我们希望等待资源都加载回来,才去做其他事情
    写代码的时候,我们会把所有的代码 都写在  window load事件中来确保 资源全部都可以使用 
     */
    window.addEventListener('load', function () {
      console.log('load 标签加载完毕-标签对应外部资源加载完毕');
    });
    // DOMContentLoaded 
    // 页面的标签 都加载完毕就触发了,不需要等待标签的内容回来
    // video标签一生成, 事件就触发 
    // load事件等待 vide标签生成了,同时 video标签内的视频也加载回来 才触发 

    // video加载 分两部
    // 只是加载标签而已 很快 DOMContentLoaded    快
    // 会去加载 标签对应的视频 比较慢  load 慢
    document.addEventListener("DOMContentLoaded",function () {
      console.log("DOMContentLoaded 标签加载完毕就触发了");
    })
  </script>

页面加载的作用

	  <!-- 以前写js 习惯写在head标签中 -->
    <script>
      // 等待标签加载完毕了,才去获取dom元素
      document.addEventListener('DOMContentLoaded', function () {
        const h1 = document.querySelector('h1');
        console.log(h1);
        h1.innerText = '我们自己修改的';
      });
      // js先执行,但是 dom元素还没有开始加载
    </script>
</head>
<body>
    <h1>大标题</h1>
    <img
      src="https://dss0.bdstatic.com/-0U0bnSm1A5BphGlnYG/tam-ogel/33867296_1452769018_259_194.jpg"
      alt=""
    />
    <!-- 
      load 作用 
      我希望  在h1标签上输出一张图片的高度
     -->
    <script>
      // window.addEventListener('load', function () {
      //   // 等待图片完全加载了 内容也回来, 才触发
      //   const img = document.querySelector('img');
      //   // 获取图片标签的宽度
      //   console.dir(img.height); // 0  因为 代码执行到这里的时候 图片的内容还没有回来

      //   document.querySelector("h1").innerHTML=img.height;
      // });
       // 现在建议把代码 写在 </body> 上面 , 先等待dom标签加载,然后才去获取dom元素
    </script>

元素大小和位置

2.1 scroll家族

使用场景:

我们想要页面滚动一段距离,比如100px,就让某些元素 显示隐藏,那我们怎么知道,页面滚动了100像素呢?

就可以使用scroll 来检测页面滚动的距离~~~

获取宽高:

获取元素的内容总宽高(不包含滚动条)返回值不带单位

scrollWidth和scrollHeight

获取位置:

获取元素内容往左、往上滚出去看不到的距离

scrollLeft和scrollTop

这两个属性是可以修改的

1649775446913

开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素

1649775501845

注意事项

document.documentElement HTML 文档返回对象为HTML元素

scrollWidth 不包含 滚动条 大小

scrollWidth 等于容器可以滚动的大小

滚动条

overflow: scroll; 上下滚动 overflow-x: scroll; 水平滚动

让文字不要换行

white-space: nowrap;

    <title>06-scroll家族.html</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      .scroll-dom {
        width: 300px;
        height: 300px;
        background-color: aqua;

        /* 滚动条 */
        /* overflow: scroll; */
        overflow-x: scroll;

        /* border: 20px; */

        /* 让文字不要换行 */
        white-space: nowrap;
      }
    </style>
</head>
<body>
    <div class="scroll-dom">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Corporis
        similique rerum ea dicta assumenda? Quam error eaque accusamus. Ipsa,
        dicta aspernatur! Consequatur odit eos, dignissimos rem iure excepturi
        commodi dicta. Lorem ipsum dolor sit amet consectetur, adipisicing elit.
        Cum, possimus ab incidunt ipsum animi reprehenderit quia deserunt odit?
        Laborum natus asperiores amet adipisci laudantium tempore nesciunt
        blanditiis quis voluptas excepturi! Lorem ipsum dolor, sit amet
        consectetur adipisicing elit. Eaque error quae, minima facilis recusandae
        cumque qui sed saepe excepturi accusamus neque, illum eius perspiciatis
        aliquid dicta ullam est et maiores!
      </div>
      <script>
        /* 
        scrollWidth  不包含 滚动条 大小 
        scrollWidth  等于容器可以滚动的大小 
         */
        const scrollDom = document.querySelector('.scroll-dom');
        // 输出它宽度高度
        console.log(scrollDom.scrollWidth);
        // console.log(scrollDom.scrollHeight);
  
        // 获取当前容器滚动了的距离
        scrollDom.addEventListener('scroll', function () {
          // console.log(this.scrollTop);// 获取当前容器的滚动距离
          console.log(this.scrollLeft); // 获取当前容器的滚动距离
        });
  
        /* 
        1 页面滚动 使用  window.addEventListener("scroll") 事件
        2 页面的滚动距离 document.documentElement.scrollTop
  
  
        1 元素滚动 dom.addEventListener("scroll")
        2 获取元素滚动的距离
          dom.scrollTop
          dom.scrollLeft
  
        3 scrollWidth 整个可以滚动的区间的宽度
        4 scrollHeight 整个可以滚动的区域的高度 
  
        小细节  PC端的滚动条大小 17px
        小细节 移动端的滚动条 不占大小 
         */
      </script>

页面滚动显示返回顶部按钮 案例

需求:当页面滚动500像素,就显示返回顶部按钮,否则隐藏, 同时点击按钮,则返回顶部

分析:

①:用到页面滚动事件

②:检测页面滚动大于等于100像素,则显示按钮

③:点击按钮,则让页面的scrollTop 重置为 0

    <!-- 返回顶部小火箭 -->
    <div class="actGotop"><a href="javascript:;" title="Top"></a></div>

    <!-- 需求:
    1.滚动出屏幕的距离超过1000的时候,出现小火箭
    2.单击小火箭能够返回到顶部 -->

    <script>
      window.addEventListener('load', function() {
        // 获取元素
        let actGotop = document.querySelector('.actGotop')
        // 为小火箭添加单击事件
        actGotop.addEventListener('click', function() {
          // 回到顶部
          document.documentElement.scrollTop = 0
        })

        // 监听页面滚动
        window.addEventListener('scroll', function() {
          // 获取页面滚动出屏幕的距离
          let top = document.documentElement.scrollTop
          // 判断卷出的距离是否大于 2000
          if (top >= 2000) {
            // 让小火箭出现
            actGotop.style.display = 'block'
          } else {
            // 让小火箭隐藏
            actGotop.style.display = 'none'
          }
        })
      })
    </script>

案例的另种做法

    <a href="javascript:"></a>
    
    <script>
        const a = document.querySelector('a')
        window.addEventListener('scroll', function(){
        //  获取页面滚动的高度
            const scrollTop = document.documentElement.scrollTop
            console.log(scrollTop);
            // 判断页面滚动高度
            if(scrollTop > 700) {
                a.style.display = 'block'
            }else{
                a.style.display = 'none'
            }
        })
        a.addEventListener('click', function(){
            // 方法一
            // window.scrollTo({
            //     top:0,
            //     behavior: 'smooth'
            // })

            //  方法二 慢慢减少为0 
            const timeId = setInterval(function(){
                document.documentElement.scrollTop -= 30

                if(document.documentElement.scrollTop === 0){
                    // 清楚定时器
                    clearInterval(timeId)
                }
            }, 10);
        })
    </script>

2.2 offset家族

使用场景:

前面案例滚动多少距离,都是我们自己算的,最好是页面 滚动到某个元素,就可以做某些事。

简单说,就是通过js的方式,得到元素在页面中的位置 这样我们可以做,页面滚动到这个位置,就可以返回 顶部的小盒子显示…

获取宽高:

获取元素的自身宽高、包含元素自身设置的宽高、padding、border

offsetWidthoffsetHeight

获取位置:

获取元素距离自己定位父级元素的左、上距离

offsetLeftoffsetTop 注意是只读属性

1649905402381

演示

    <div class="box">
        <div class="son"></div>
    </div>
    <script>
        const son = document.querySelector('.son')
        // offset 的宽高包含 内容 + position + border
        console.log(son.offsetWidth, son.offsetHeight);
        // 如果有定位 便参照定位的父容器 没有就一直往上找 直到屏幕
        console.log(son.offsetLeft, son.offsetTop);
    </script>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      .offset {
        width: 300px;
        height: 300px;
        background-color: aqua;

        overflow: scroll;
       margin-left: 10px;
      }
      .parent{
        position: fixed;
        left: 400px;
        top: 30px;
        background-color: salmon;
        width: 400px;
        height: 400px;
      }
    </style>
</head>
<body>
    <div class="parent">
        <h1>标题</h1>
        <div class="offset"></div>
      </div>
      <script>
        const offsetDom = document.querySelector('.offset');
  
        // 获取宽度和高度 包含这滚动条的大小 
        console.log(offsetDom.offsetWidth);// 300 
        console.log(offsetDom.offsetHeight);// 300
  
        // console.log(offsetDom.scrollWidth); // 283
        // console.log(offsetDom.scrollHeight);// 283 
  
        // 获取当前元素距离 定位了的父元素的大小(找不到定位了的父元素,相对于页面来计算)
        console.log(offsetDom.offsetLeft);
        console.log(offsetDom.offsetTop);
  
  
        /* 
        总结 offset家族
        1 offsetWidth  获取元素的宽度 包含这滚动条
        2 offsetHeight 获取元素的高度 包含这滚动条
        3 offsetLeft 获取定位了的父元素的 水平距离 左 
        4 offsetTop 获取定位了的父元素的 垂直距离 上
         */
      </script>

2.3 client家族

获取宽高:

获取元素的可见部分宽高(不包含边框,滚动条等)

clientWidthclientHeight

获取位置:

获取左边框和上边框宽度

clientLeftclientTop 注意是只读属性

scollWidth 获取容器的宽度(包含滚动的区域)

offsetWidth 获取可视区域的宽度(包含滚动条)

clientWidth 获取可视区域的宽度(不包含滚动条)

scrollLeft 获取左侧滚动的距离

offsetLeft 获取和已经定位了的父级元素的左距离

获取边框的大小

clientLeft 获取左边框的大小

clientTop 获取上边框的大小

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      .client {
        width: 300px;
        height: 300px;
        background-color: aqua;
        margin: 100px auto;

        overflow: scroll;

        border-left: 1px solid #000;
        border-right: 1px solid red;
      }
    </style>
</head>
<body>
    <div class="client">
        <h1>1</h1>
        <h1>2</h1>
        
        <h1>98</h1>
        <h1>99</h1>
        <h1>100</h1>
      </div>
      <script>
        const clientDom = document.querySelector('.client');
        // 宽度和高度
        console.log(clientDom.clientWidth); // 不包含 滚动条(类似 scrollWidth)
        console.log(clientDom.clientHeight); // 不包含 滚动条(类似 scrollHeight)
  
        // 获取边框的大小
        console.log(clientDom.clientLeft); // 左边框
        console.log(clientDom.clientRight); // 有没有? undefined
        console.log(clientDom.clientTop); // 上边框  
  
        // scollWidth     获取容器的宽度(包含滚动的区域)
        // offsetWidth    获取可视区域的宽度(包含滚动条)
        // clientWidth    获取可视区域的宽度(不包含滚动条)
  
        // scrollLeft    获取左侧滚动的距离
        // offsetLeft    获取和已经定位了的父级元素的左距离
        // clientLeft    获取左边框的大小 
      </script>

总结

1、offset家族

获取元素自身大小:包括自身设置的宽高、padding、border

获取元素距离定位父级的左和上距离 只读属性

2、client家族

获取元素可见区域的大小

获取元素左、上边框距离 只读属性

3、scroll家族

获取元素内容的总大小

获取元素向左向上滚出去看不见的距离 可读写属性

会在窗口尺寸改变的时候触发事件: resize

语法:

// 页面大小发生变化了就会触发的事件 resize window来绑定
      window.addEventListener('resize', function (event) {
        // 执行代码
      });

检测屏幕宽度:

      window.addEventListener('resize', function (event) {
        // 获取当前页面的宽度
        console.log(document.body.offsetWidth);
      });

演示

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      div {
        width: 1rem;
        height: 1rem;
        background-color: aqua;
        font-size: 1rem;
      }
    </style>
</head>
<body>
    <div>div</div>
    <script>
      // 页面大小发生变化了就会触发的事件 resize window来绑定
      window.addEventListener('resize', function (event) {
        console.log('页面大小发生变化了');
        // 移动端屏幕适配 rem   淘宝js库,flexible.js  作用  设置html的字体大小 为当前页面的宽度的十分之一
        // 获取当前页面的宽度
        console.log(document.body.offsetWidth);
        // 设置页面html标签的字体大小为屏幕的十分之一
        document.documentElement.style.fontSize = document.body.offsetWidth / 10 + 'px';

        // 响应式布局的时候  发一个js文件  方便根据当前页面的宽度 告诉我们屏幕的种类和宽度
        const width = document.body.offsetWidth;

        if (width > 1200) {
          document.querySelector('title').innerText = `大屏幕 ${width}`;
        } else if (width > 992) {
          document.querySelector('title').innerText = `中等屏幕 ${width}`;
        } else if (width > 768) {
          document.querySelector('title').innerText = `小屏幕 ${width}`;
        } else {
          document.querySelector('title').innerText = `极小屏幕 ${width}`;
        }
      });
    </script>