三大家族?offset、scroll、client

243 阅读2分钟

1、初识 offset 家族

  • offset 家族:获取元素 自身真实宽高与位置
  • offsetWidth/offsetHeight:自身真实宽或高=content+padding*2+border*2
  • offsetLeft:自身左外边框到父元素左内边框的距离
  • offsetTop:自身上外边框到定位父元素上内边框的距离
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            background-color: yellowgreen;
        }
    </style>
</head>

<body>
    <div class="box">
        <!-- 这里是乱数假文哦,测试用 -->
     Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis, labore, sequi nesciunt reiciendis hic omnis sint deleniti provident corporis assumenda earum eius quam ducimus odit aperiam libero exercitationem, suscipit consequatur?
    </div>
    <script>
        let box=document.querySelector('.box')
        console.log(box.offsetWidth,box.offsetHeight,'1')// 200 200
        console.log(box.offsetLeft,box.offsetTop,'2')// 8 8 浏览器默认的 8px 边距
        console.log(box.offsetRight,box.offsetBottom,'3')// undefined undefined 
    </script>
</body>

</html>

2、初识 scroll 家族

  • scroll 家族:获取元素 内容 真实宽高与位置
  • scrollWidth/scrollHeight:内容真实宽或高
  • scrollLeft:滚动条滚动左边的距离
  • scrillTop:滚动条滚动上边的距离
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            background-color: yellowgreen;
            overflow: auto;
        }
    </style>
</head>

<body>
    <div class="box">
        <!-- 这里是乱数假文哦,测试用 -->
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro blanditiis, odio cum veritatis, dolorem ab optio voluptas reprehenderit eaque eos recusandae consequatur quam debitis, officiis quidem dignissimos. Fugiat, quia repellendus.
    </div>
    <script>
        let box=document.querySelector('.box')
        console.log(box.scrollWidth,box.scrollHeight,'1')// 183 250 
        console.log(box.scrollLeft,box.scrollTop,'2')// 0 0
        console.log(box.scrollRight,box.scrollBottom,'3')// undefined undefined (亲测无法获取)
    </script>
</body>

</html>

3、初识 client 家族

  • client:获取元素 可视区域 真实宽高与位置
  • clientWidth/clientHeight:可视区域真实宽或高
  • clientLeft:可视区域左边框宽度
  • clientTop:可视区域上边框宽度
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            background-color: yellowgreen;
            border: 20px solid orange;
        }
    </style>
</head>

<body>
    <div class="box">
        <!-- 这里是乱数假文哦,测试用 -->
     Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis, labore, sequi nesciunt reiciendis hic omnis sint deleniti provident corporis assumenda earum eius quam ducimus odit aperiam libero exercitationem, suscipit consequatur?
    </div>
    <script>
        let box=document.querySelector('.box')
        console.log(box.clientWidth,box.clientHeight,'1')// 200 200
        console.log(box.clientLeft,box.clientTop,'2')// 20 20 
        console.log(box.clientRight,box.clientBottom,'3')// undefined undefined (笔者亲测无法获取)
    </script>
</body>

</html>

4、初步总结三大家族

  • 获取的都是 number数字类型
  • 只能获取不能修改
  • 注意:scrollLeftscrollTop 可以修改滚动条的位置
  • 应用场景:
    • scroll 家族 :获取网页滚动距离
    • offset 家族 :通常配合 scroll家族 做固定导航、电梯导航
    • client 家族 :响应式布局

5、深入理解三大家族(综合案例)

scroll 家族 :获取网页滚动距离示例

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title>标题</title>
    <style>
        body {
            width: 3000px;
            height: 3000px;
        }
    </style>
</head>

<body>
    <script>
        // let html = document.documentElement
        // window.onscroll = function () {
        //     console.log('滚动条滚动了')
        //     console.log(html.scrollLeft, html.scrollTop)// 带小数点,可以取整
        // }

        // ◆1注册滚动条事件: window.onscroll
        window.onscroll = function () {
            console.log('滚动条滚动了啦啦啦')
            /* ◆2获取网页滚动条距离 */
            console.log(parseInt(document.documentElement.scrollLeft), parseInt(document.documentElement.scrollTop))
        }

    </script>
</body>

</html>

offset 家族:电梯导航示例(配合 scroll 家族)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    body {
      height: 3000px;
    }

    .box {
      display: flex;
      margin: 200px auto;
    }

    .aside {
      position: fixed;
      left: 150px;
      top: 200px;
    }

    .aside .active {
      background-color: red;
    }

    .aside>div {
      width: 100px;
      height: 40px;
      margin-top: 10px;
      line-height: 40px;
      text-align: center;
      background-color: #ccc;
      cursor: pointer;
    }

    .content {
      margin: 100px auto;
    }

    .content>div {
      width: 500px;
      height: 400px;
      margin-top: 20px;
      background-color: pink;
      cursor: pointer;
    }

    .content .content1 {
      background-color: purple;
    }

    .content .content2 {
      background-color: orange;
    }

    .content .content3 {
      background-color: skyblue;
    }

    .content .content4 {
      background-color: green;
    }
  </style>
</head>

<body>
  <!-- 大盒子 -->
  <div class="box">
    <!-- 侧边导航栏 -->
    <div class="aside">
      <div class="items1 active">导航1</div>
      <div class="items2">导航2</div>
      <div class="items3">导航3</div>
      <div class="items4">导航4</div>
    </div>
    <!-- 中间主体栏 -->
    <div class="content">
      <div class="content1">内容1</div>
      <div class="content2">内容2</div>
      <div class="content3">内容3</div>
      <div class="content4">内容4</div>
    </div>
  </div>

  <script>
    /* 1.获取数据 */
    let asideList = document.querySelectorAll('.aside>div')//获取左侧导航栏
    let contentList = document.querySelectorAll('.content>div')//获取左侧导航栏
    let html = document.documentElement//获取html
    console.log(asideList, contentList, html)//测试数据

    /* 2.注册事件 */
    // 点击左侧导航栏
    for (let i = 0; i < asideList.length; i++) {
      asideList[i].onclick = () => {
        // 上一个被点击的元素移除样式
        document.querySelector('.aside .active').classList.remove('active')
        // 当前被点击的元素新增样式
        asideList[i].classList.add('active')
        html.scrollTop = contentList[i].offsetTop
      }
    }
    // 点击右侧滚动
    window.onscroll = () => {
      for (let i = 0; i < contentList.length; i++) {
        // 滚动条滚动的距离(这个距离可以自己把控)
        if (html.scrollTop >= contentList[i].offsetTop - 200) {
          // 上一个内容对应的左侧导航按钮移除样式
          document.querySelector('.aside .active').classList.remove('active')
          // 当前内容对应的左侧导航按钮添加样式
          asideList[i].classList.add('active')
        }
      }
    }
  </script>
</body>

</html>

client 家族:响应式布局示例

  • 1.响应式布局:一个页面适配多个不同的设备
    • 大PC >1200px
    • 小PC 992px-1200px
    • 平板 768px-992px
    • 手机 <768px
  • 2.响应式布局原理:根据设备尺寸的不同,加载不同的样式
  • 3.响应式布局流程
    • (1)给页面注册一个尺寸变化事件(视口变化): window.onresize
    • (2)获取页面可视区域大小(视口大小): document.documentElement.clientWidth
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        // 获取 html 和 body
        let html = document.documentElement
        let body = document.body

        // 注册事件
        window.onresize = function () {
            let vw = html.clientWidth
            let vh = html.clientHeight
            console.log(vw, vh);
            // 视口宽度 大于 1200 px 显示 红色背景
            if (vw > 1200) {
                body.style.backgroundColor = 'red'

            }
            // 视口宽度 大于 992 px 小于等于 1200 px 显示 橙色背景
            else if (vw > 992) {
                body.style.backgroundColor = 'orange'

            }
            // 视口宽度 大于 768 px 小于等于 992 px 显示 黄色背景
            else if (vw > 768) {
                body.style.backgroundColor = 'yellow'

            }
            // 视口宽度 小于等于 768 px 显示 绿色色背景
            else {
                body.style.backgroundColor = 'green'

            }
            // 也可以用来判断横屏竖屏
            // if (vw<vh) {
            //     alert('竖屏')
            // }else{
            //     alert('横屏')
            // }
        }
    </script>
</body>

</html>