JavaScript 位置大小相关属性 | offsetX/screenX - clientWidth/offsetWidth - Intersection Observer API

JavaScript 位置与大小属性

学习文章:https://blog.csdn.net/qq_44603011/article/details/117768212
https://blog.csdn.net/weixin_61597234/article/details/134878221
https://juejin.cn/post/6961383795866435591
https://juejin.cn/post/7146441070828584968

元素自身Element有关的位置属性

element.offsetParent 获取包含element的祖先元素中,层级最近的定位元素

获取到的元素需要包含三个条件
1.是Element的祖先元素
2.最靠近Element
3.是定位元素,即position属性不为static

案例
box:有3个祖先元素:
1.层级为3的定位元素 position-outer
2.层级为2个定位元素 position-inner
3.层级为1定位元素 not-position
=> positon-inner才同时满足上面关于offsetParent的3个条件

<div class="position-outer" style="position: relative;">
    <div class="position-inner" style="postion: relative;">
        <div class="not-position">
        	<div class="box">
        	</div>
        </div>
    </div>
</div>

offsetLeft / offsetTop 只读属性 获取元素距离带定位父元素的位置

offsetLeft :element相对于offsetParent左边界的偏移值
offsetTop :element相对于offsetParent上边界的偏移值

在这里插入图片描述

滚动条相关属性

element.scrollTop属性

element.scrollTop: “元素中的内容” 超出 “元素上边界” 部分的高度,也可以理解为滚动条滚动了多少距离(滚动距离)

在这里插入图片描述

如果失效需要排查是否设置给能滚动的元素,比如设置了overflow: auto的元素

Element.scrollTo()方法
语法1:Element.scrollTo(x-coord, y-coord)
x-coord:滚动 据Element左上角,X方向x-coord像素
y-coord:滚动 据Element左上角,Y方向y-coord像素

语法2:Element.scrollTo(options)
options对象

属性描述
left属性等同于x-coord
top属性等同于y-coord
behavior动画效果smooth 表示平滑滚动并产生过渡效果
instant 表示滚动会直接跳转到目标位置,没有过渡效果
auto 或缺省值表示浏览器会自动选择滚动时的过渡效果

element.getBoundingClientRect()返回DOMRect 对象

位置是相对于浏览器窗口当前可以看见的区域(不包含浏览器中看不见/滚动条没滚到的区域和工具栏)

top:图中红色线表示top的取值区域,最外层边框到窗口顶部的距离。 — 以下案例是90
left:图中蓝色线表示left的取值范围,可知是由最外层边框到窗口左侧的距离。 – 以下案例是120
bottom:图中紫色线表示bottom的取值范围,可知是元素由最外层边框到窗口顶部的距离。 --以下案例是90+10+10+300+10+10 =
430 = height(340)+y(90)
right:图中绿色线表示right的取值范围,可知是元素由最外层边框到窗口顶部的距离。 – 以下案例是120+10+10+300+10+10 = 460 = x+width
在这里插入图片描述

元素自身Element有关的大小属性

属性描述特点
Element.clientWidth内边距(padding)+ 内容属性值会四舍五入为一个整数
HTMLElement.offsetWidth边框(border)+padding+内容+ 滚动条宽度(如有)属性值会四舍五入为一个整数,不带单位
Element.scrollWidth包括由于溢出而无法在屏幕上显示的部分(包含伪元素) + clientWidth属性值会四舍五入为一个整数
Element.getBoundingClientRect().widthpadding + border-width + 内容标准盒子= width/height + padding + border-width
box-sizing: border-box 盒子 = width/height

在这里插入图片描述

在这里插入图片描述
scrollWidth不包含边框border
在这里插入图片描述

clientWidth为什么为0

  1. 元素不显示时 display: none获取为0
    猜测原因渲染树中只包含可见的节点,忽略所有不可见(这里应该指display: none)的节点。由于visibility: hidden的元素只是看不见,但还是会占据位置所以需要计算节点的大小位置信息所以在渲染树中,所以可以获取到offsetWidth

  2. 行内元素获取时为0,行内元素width属性不生效
    常见的行内元素:span、a、 img、 input、textarea、select、label
    常见的块级元素:div、p、table、form

offset系列和style的区别

offsetstyle
可以得到任意样式表中的样式值只能得到行内样式表中的样式值
获得的数值是没有单位的style.width得到的值是带有单位的字符串offsetWidth包含padding+border+width
offsetWidth是只读属性style.width可读写
想要获取元素大小位置,用offset更合适想要给元素更改值,则需要用style

案例

1.判断元素是否滚动到底

scrollTop + scrollHeight + clientHeight

scrollTop 是一个非整数,而 scrollHeightclientHeight 是四舍五入值,因此确定滚动区域是否滚动到底的唯一方法是查看滚动量是否足够接近某个阈值

scrollHeight = 由于溢出而无法在屏幕上显示的部分(也就是滚动距离) + clientHeight
所以判断是否到底的公式是,这里的阈值取1

Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1

存在问题:不同分辨率有误差

2.内容超出后显示滚动条,自动滚动到最底部

判断是否存在滚动条的逻辑:出现滚动条意味着元素空间将大于其内容显示区域

el.scrollHeight > el.clientHeight

设置滚动到最底部
直接设置的dom元素的js属性,所以如果设置过渡动画transition是没有效果的

container.scrollTop = container.scrollHeight;

事件源event位置相关属性

在这里插入图片描述

属性相对区域说明
offsetX
offsetY
相对于事件源元素假设点击黄色盒子打印offsetX/offsetY,此时的原点为黄色盒子的左上角,X轴正向朝右,Y轴正向朝下
clientX
clientY
相对于浏览器窗口当前可以看见的区域(不包含浏览器中看不见/滚动条没滚到的区域和工具栏)原点为灰色区域的左上角,X轴正向朝右,Y轴正向朝下
pageX
pageY
相对于整个页面(document、html区域?)pageX = ev.clientX + 横向滚动条滚动的距离
screenX
screenY
鼠标相对于用户显示器屏幕原点在显示器屏幕的左上角,X轴正向朝右,Y轴正向朝下

Intersection Observer API 判断元素相交性

Intersection Observer API提供了一种异步检测目标元素与祖先元素或视口(可统称为根元素)相交情况变化的方法。

说明:API是异步的,触发时机是当浏览器空闲时执行观察器。不会随着目标元素的滚动同步触发,原因是IntersectionObserver API是通过requestIdleCallback()实现。

使用场景:某个元素是否可见或相交

概念
目标元素target:需要监听的元素
根元素root
交叉比intersection ratio:目标元素与根元素的交集相对于目标元素百分比,取值范围 0.0-1.0,没办法具体到xpx的像素。
阈值threshold:回调函数触发的条件。

IntersectionObserver()构造器

语法:new IntersectionObserver(callback[, options])

参数

  1. callback(entries,observer)回调函数:当交叉比超过阈值会触发
    • entries: 由IntersectionObserverEntry对象组成的数组
    • observer :被调用回调的IntersectionObserver实例
  2. options可选配置对象
    • root根元素:必须是目标元素的父级或祖先,默认为浏览器的可视窗口(指定null也是)
    • rootMargin根元素的扩缩边距:值格式同margin,用于控制根元素的哪个位置开始算与目标元素相交, 默认值为"0px 0px 0px 0px"。
    • threshold阈值:回调函数触发的条件,取值范围为0.0-1.0,默认为0.0。当传入数值类型时,只会触发一次。当传入数值类型时,只会触发一次。

注意点:当IntersectionObserver 对象被创建时,就会被指定所监听的根元素、阀值等信息,并且被创建后无法更改

IntersectionObserverEntry对象

IntersectionObserverEntry:接口描述了目标元素与其根元素容器在某一特定过渡时刻的交叉状态。

IntersectionObserverEntry 对象的七个只读属性

属性说明
target返回目标元素,表示目前正监听的元素
isIntersecting目标元素刚出现在根元素可视区时返回 true
目标元素从根元素可视区消失返回 false
出现和消失都会触发 callback 函数
boundingClientRect返回目标元素的矩形区域的信息,返回结果与element.getBoundingClientRect()相同
rootBounds返回根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null
intersectionRect返回目标元素与视口(或根元素)交叉区域的信息
intersectionRatio返回目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为 1,完全不可见时小于等于 0
time返回一个记录从IntersectionObserver的时间原点到交叉被触发的时间的时间戳
IntersectionObserver实例对象

三个可读属性:与构造器方法第二个可选对象的属性名一致。

四个方法

方法名描述
observe(target)开始监听指定目标元素
unobserve(target)停止监听指定的目标元素
takeRecords()返回所有观察目标的 IntersectionObserverEntry 对象数组 – 唯一获取 IntersectionObserverEntry 对象的方法
disconnect()使 IntersectionObserver 对象停止全部监听工作

案例

1.判断元素是否滚动到底 = 元素是否全部可见

之前的案例存在问题:不同分辨率有误差
解决办法:使用Intersection Observer API实现

如果元素(在这种情况下是整个body)完全出现在视窗内(即未被遮挡),isIntersecting 属性为 true;如果元素完全不在视窗内(即被遮挡),isIntersecting 属性为 false。


let isScrollBottom = false;

const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) { // 正相交
      isScrollBottom = false;
    } else { // 没有相交,全部展现
      isScrollBottom = true;
    }
  });
}, {threshold: 0});

observer.observe(document.querySelector('body'));

if (isScrollBottom) {
  console.log('滚到底部');
} else {
  console.log('未滚到底部');
}
2.图片懒加载

图片懒加载学习笔记

  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值