Intersection Observer API
交叉观察器 API(Intersection Observer API)提供了一种异步检测目标元素与祖先元素或顶级文档的视口相交情况变化的方法,例如,可以观察判断一个div(有大小的)盒子在是否出现在窗口(window)中,你也可以指定它的一个父级元素,像html,body,等等。
观察器对象
构造函数
let observer = new IntersectionObserver(entries => {
},{
root: null,
rootMargin: '0px',
threshold: 0.5 // 出现50%
})
callback:回调函数,有一个参数entries,
entries:数组,存放描述观察器和被观察对象的状态的对象(被观察的对象可以有多个)---IntersectionObserverEntry
IntersectionObserverEntry:对象,内部有7个属性和值
boundingClientRect:返回包含目标元素的边界信息的DOMRectReadOnly. 边界的计算方式与 Element.getBoundingClientRect() 相同。
intersectionRatio:返回intersectionRect
与 boundingClientRect
的比例值。
intersectionRect:返回一个 DOMRectReadOnly 用来描述根和目标元素的相交区域。
isIntersecting:返回一个布尔值,如果目标元素与交叉区域观察者对象 (intersection observer) 的根相交,则返回 true
.如果返回 true
, 则 IntersectionObserverEntry
描述了变换到交叉时的状态; 如果返回 false
, 那么可以由此判断,变换是从交叉状态到非交叉状态。
rootBounds:返回一个 DOMRectReadOnly 用来描述交叉区域观察者 (intersection observer) 中的根。
target:与根出现相交区域改变的元素 (Element).
time :返回一个记录从 IntersectionObserver
的时间原点 (time origin) 到交叉被触发的时间的时间戳 (DOMHighResTimeStamp).
option: 对象,内部有3个属性和值,
root:根元素,用作视口的元素,用于检查指定元素的可见性,必须是该指定元素的祖先。如果未指定或为 null
,则默认为浏览器视口。例如,一个div是body的子元素,那么body就可以是这个div的root。
rootMargin:根元素周围的边距。其值可以类似于 CSS margin 属性,例如 "10px 20px 30px 40px"
(上、右、下、左)。这些值可以是百分比。在计算交叉点之前,这组值用于增大或缩小根元素边框的每一侧。默认值为全零。
threshold:阈值,一个数字或一个数字数组,表示目标可见度达到多少百分比时,观察器的回调函数就应该执行(当目标在根元素中出现指定的比例时会触发一次回调)。如果只想在能见度超过 50% 时检测,可以使用 0.5 的值。如果希望每次能见度超过 25% 时都执行回调,则需要指定数组 [0, 0.25, 0.5, 0.75, 1]。默认值为 0(这意味着只要有一个像素可见,回调就会运行)。值为 1.0 意味着在每个像素都可见之前,阈值不会被认为已通过。
可以看到实例化的观察器对象,
实例方法
disconnect()
使 IntersectionObserver
对象停止监听目标。
observe()
使 IntersectionObserver
开始监听一个目标元素。
ItakeRecords()
返回所有观察目标的 IntersectionObserverEntry 对象数组。
unobserve()
使 IntersectionObserver
停止监听特定目标元素。
观察示例
新建一个div盒子,当它出现在视口占50%时,改变它的颜色
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视口观察</title>
<style>
.content{
height: 200vh;
}
.box{
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="content"></div>
<div class="box"></div>
<div class="content"></div>
<script src="index.js"></script>
</body>
</html>
index.js:
const box = document.getElementsByClassName('box')[0];
const observer = new IntersectionObserver(entries => {
// console.log(entries);
// 如果 intersectionRatio 为 0,则目标在视野外,
// 我们不需要做任何事情。
if (entries[0].intersectionRatio <= 0) return;
if(entries[0].isIntersecting >= observer.thresholds[0]){
console.log('元素进入视口50%');
}
},{
root: null,
rootMargin: '0px',
threshold: 0.5 // 出现50%
})
observer.observe(box);//观察box
console.log(observer);
再添加改变颜色
const box = document.getElementsByClassName('box')[0];
const observer = new IntersectionObserver(entries => {
// // console.log(entries);
// // 如果 intersectionRatio 为 0,则目标在视野外,
// // 我们不需要做任何事情。
// if (entries[0].intersectionRatio <= 0) return;
if(entries[0].isIntersecting >= observer.thresholds[0]){
console.log('元素进入视口50%');
box.style.backgroundColor = 'blue';
}else{
console.log('元素离开视口50%');
box.style.backgroundColor = 'red';
}
},{
root: null,
rootMargin: '0px',
threshold: 0.5 // 出现50%
})
observer.observe(box);//观察box
console.log(observer);
这样就成功观察到了一个元素是否出现再视口,并对其进行操作,
实际应用中可以实现图片的懒加载,当视口中出现图片时在将图片加载出来