分享对js中元素的大小和坐标理解

147 阅读6分钟

1--js中的元素大小分类

首先关于js元素大小的分类,常用的分为以下三种:

  1. offsetWidth、offsetHeight.
  2. clientWidth、clientHeight.
  3. scrollWidth、scrollHeight。

1、offsetWidth

展示MDN中对offsetWidth的图解,介绍了offsetwidth包含的布局属性。

HTMLElement.offsetWidth 是一个只读属性,返回一个元素的布局宽度。一个典型的(译者注:各浏览器的 offsetWidth 可能有所不同)offsetWidth 是测量包含元素的边框 (border)、水平线上的内边距 (padding)、竖直方向滚动条 (scrollbar)(如果存在的话)、以及 CSS 设置的宽度 (width) 的值。

主要描述offsetWidth = content(内容区域) + padding(内边距) + border(边框) + 滚动条(如果存在)

2、clientWidth

展示MDN中对clientWidth的图解,介绍了clientWidth包含的布局属性。 image.png

只读属性 Element.clientWidth 对于没有定义 CSS 或者内联布局盒子的元素为 0;否则,它是元素内部的高度(以像素为单位),包含内边距,但不包括边框、外边距和垂直滚动条(如果存在)

主要描述 clientWidth = content(内容区域) + padding(内边距)

3、scrollWidth

展示MDN中对scrollWidth的介绍。 Element.scrollWidth 这个只读属性是元素内容宽度的一种度量,包括由于 overflow 溢出而在屏幕上不可见的内容。

scrollWidth值等于元素在不使用水平滚动条的情况下适合视口中的所有内容所需的最小宽度。宽度的测量方式与clientWidth相同:它包含元素的内边距,但不包括边框,外边距或垂直滚动条(如果存在)

主要描述 scrollWidth = content(内容区域) + padding(内边距) + 溢出部分(如果存在)

代码演示

首先创建一个div。这里使用的是css3的盒子模型。box-sizing: content-box | border-box

计算方式为:width = content + padding + border,宽度指定之后就不会改变了,padding与border的变大,会让content减小,因为width是定值。

   box-sizing: border-box;
            width: 200px;
            height: 200px;
            border: 10px solid black;
            background-color: seagreen;
            padding: 10px;
image.png

现在使用浏览器打开这个html文档,按 CTRL + SHIFT + j 打开控制台,按照下面的步骤来操作就可以直观的看到三个属性了。

image.png

显示的这个数据基础上是我们设置了css3的怪异盒模型,如果没有设置,显示结果不一样

image.png

我们以css3盒子为准则分析以下显示的三条数据

1、offsetWidth = 200。因为盒子的总宽度为200px,设置border与padding只会让content(内容区)缩小,所以 offsetWidth = content + padding + border还是200px。

2、clientWidth = 181。分析知 content=160px,由于没有右侧滚动条存在,所以clientWidth=180px,为啥是181呢?,众所周知,js计算会有误差,例如0.1+0.2 != 0.3。 计算公式:clientWidth = content + padding,

3、由于div中没有溢出自身元素的内容,所以clientWidth == scrollWidth,但是如果有一条元素溢出了呢? 在div中放一段文字,并在div设置上不换行 white-space: nowrap;

image.png

再次打开浏览器时,会发现scrollWidth的值与clientWidth不一样了。

scrollWidth = content + padding + 溢出部分(如果存在)

image.png

[推荐大家没看懂的看看这个](你必须知道的 clientWidth, offsetWidth, scrollWidth. - 掘金 (juejin.cn))

2--js中的坐标理解

js中关于坐标的获取方式主要有三种

  1. offsetX,offsetY
  2. clientX,clientY
  3. pageX,pageY
image.png 图片描述三种获取坐标位置 image.png

1、offsetX

offsetX:鼠标点击位置距离盒子内容区域左侧的距离。

其中内容区域包括 content + padding,不包括border边框。

通俗来讲,以padidng(如果存在) | content为Y轴,点击左侧(内容区域)显示正值,点击右侧(border)显示负值。

代码演示:其中在div上设置了padding为30px,border为10px

 //css
 #box1 {
            width: 400px;
            height: 400px;
            background-color: #bfa;
            overflow: auto;
            border: 10px solid #000;
            padding: 30px;
        }
          .test{
            width:50%
            height:100%
            background-color: red;
        }
// html
<div id="box1">
<div class="test">我是div标签</div>
</div>
//js
      box1.addEventListener('click', (e) => {
            // console.log(e); //e为事件对象,点击不同的元素会传入不同元素的事件对象
            console.log(e.offsetX, e.offsetY);
        })

其中id为box1的div拥有10px的黑色边框,30px的内边距,红色区域为content内容展示区域,当点击黑色边框时会打印负的距离,点击绿色区域会打印距离左侧的距离。

这里注意一下,当我们点击红色区域时,由于传递的事件对象e为点击的元素,所以会打印红色区域距离自身左侧的距离。可以通过e.target打印触发的元素

image.png

2、clientX

MouseEvent.clientX 是只读属性,它提供事件发生时的应用客户端区域的水平坐标 (与页面坐标不同)。鼠标点击位置距离浏览器可视区域的左侧的距离

clientX中的可视区域 = content + padding + border

3、pageX

pageX举例子没有pageY方便,这里我们使用pageY来举例子。

当我们写的div高度没有超过浏览器可视区域的高度时,pageY === clientY,一旦页面div的高度超过了浏览器可视区域的高度,那么pageY = clientY + 超过页面的高度(scrollY)。参考下面这张图,我们会发现Y轴是大于浏览器可视区域的(滚动条),所以pageY就会很大。

image.png

足球移动

box1为一个封闭的空间,box2相当于一个小球,点击box1的位置,box2就会向这个位置移动,且不能越界。 `

    #box1 {
        width: 400px;
        height: 400px;
        background-color: seagreen;
        background-image: url(../linguess.png);
        border: 1px solid red;
        /* 设置定位 */
        position: relative;
        left: 0;
        top: 0;
        margin: 100px auto;
    }

    #box2 {
        width: 60px;
        height: 60px;
        background-color: darkblue;
        border: 1px solid red;
        position: relative;
        left: 0;
        top: 0;
        /* 设置动画 */
        transition: all 0.7s ease;
        border-radius: 50%;
    }
<div id="box1">
    <div id="box2"></div>
</div>

<script>
    let box1 = document.querySelector("#box1");
    let box2 = document.querySelector("#box2");
    // 点击大盒子,获取点击位置的坐标,然后赋值给小盒子
    // offsetX,offsetY 相对于带有定位的父元素的位置,
    // clientX,clientY 相对于浏览器窗口的位置


    box1.onclick = (e) => {
        // 存储点击父元素的坐标
        let box1OffsetX = e.offsetX;
        let box1OffsetY = e.offsetY;

        // 获取box2的宽度与长度的一半
        let box2Width = box2.offsetWidth / 2;
        let box2Height = box2.offsetHeight / 2;

        console.log(box1OffsetX, box1OffsetY);
        // 设置box2的坐标
        box2.style.top = box1OffsetY - box2Height + "px";
        box2.style.left = box1OffsetX - box2Width + "px";

        // 判断越界条件
        // x轴越界
        if (box1OffsetX + box2Width > box1.offsetWidth) {
            box2.style.left = box1.offsetWidth - 2 * box2Width + "px";
        }
        // y轴越界
        if (box1OffsetY + box2Height > box1.offsetHeight) {
            box2.style.top = box1.offsetHeight - 2 * box2Height + "px";
        }
        // 左边界:如果box1的左边距的距离小于小盒子的宽度的一半,那么小盒子就贴着左边界的位置
        if(box1OffsetX - box2Width < 0){
            box2.style.left = 0;
        }
        // 上边界:如果box1的上边距的距离小于小盒子的宽度的一半,那么小盒子就贴着上边界的位置
        // 因为box1的点就是box2的中心点
        if(box1OffsetY - box2Height < 0){
            box2.style.top = 0;
        }
    }

</script>

实现下拉刷新

使用到的clientHeight、scrollHeight、scrollTop属性

其中clientHeight、scrollHeight已经提到,scrollTop的值为在一个盒子中,滚动条距离顶部的距离,初始值为0

image.png

js代码执行思路:当滚动到距离底部30px时,获取新的xxx资源

  if (scrollTop + clientHeight >= scrollHeight - 20) {
      console.log('到达底部,可以进行加载更多操作');
  }

image.png