IntersectionObserver可以实现类似于监听目标元素的祖先元素与视窗的交叉状态,简单地说就是能监听到某个元素是否会被我们看到,当我们看到这个元素时,可以执行一些回调函数来处理某些事务。
IntersectionObserver的小试验
<!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>
<style>
#full {
height: 1200px;
background-color: #f22;
}
#test {
height: 100px;
background-color: #3f3;
}
</style>
</head>
<body>
<div id="full"></div>
<div id="test"></div>
<script>
var io = new IntersectionObserver((entries) => {
console.log('entries: ', entries);
})
io.observe(document.getElementById('test'));
</script>
</body>
</html>
在这个小试验中,可以看到每次看到test div时都会在命令行console出对应的内容,而在我们第一次进入页面时就会打印出内容,即使我们没有见到这个元素。接下来开始解析IntersectionObserver的内容。
IntersectionObserver学习
API
构造IntersectionObserver对象
可以通过new运算符来构造IntersectionObserver对象
var io = new IntersectionObserver(callback, option);
这里的callback是回调函数,option是配置对象
属性
1.root(只读)
所监听对象的具体祖先元素。如果未传入值或值为null
,则默认使用顶级文档的视窗。
2.rootMargin(只读)
计算交叉时添加到根边界盒bounding box的矩形偏移量, 可以有效的缩小或扩大根的判定范围从而满足计算需要。此属性返回的值可能与调用构造函数时指定的值不同,因此可能需要更改该值,以匹配内部要求。所有的偏移量均可用px或百分比来表达, 默认值为"0px 0px 0px 0px"。因为该属性是只读的,要修改该属性需要在构建时option配置好。
3.thresholds(只读)
一个包含阈值的列表, 按升序排列, 列表中的每个阈值都是监听对象的交叉区域与边界区域的比率。当监听对象的任何阈值被越过时,都会生成一个通知(Notification)。如果构造器未传入值, 则默认值为0。
方法
observe(element):监听某个元素,传入要监听的元素作为参数
unobserve(element):停止监听某个元素,传入停止监听的元素作为参数
disconnect():使监听器停止工作
takeRecords():返回所有正在监听的元素的IntersectionObserverEntry对象数组
option对象
IntersectionObserver对象构造时第二个参数用于配置option对象,该对象可设置下列属性
threshold
该属性设置目标元素可见的占百分比多少时触发回调函数,配置为一个数组,每达到其中一个值就触发回调函数,默认值为[0]
var io = new IntersectionObserver((entries) => {
console.log('entries: ', entries[0].intersectionRatio);
}, {
threshold: [0, 0.5, 1]
})
通过intersectionRatio可以看到目标元素现在的可见比例
root
root属性用于指定监听元素的根元素,即用于检测交叉区域的元素,看一下下面的案例
<!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>
<style>
#full {
height: 1200px;
background-color: #f22;
}
#container {
height: 200px;
background-color: #22f;
overflow: scroll;
}
#other {
height: 200px;
}
#test {
height: 100px;
background-color: #3f3;
}
</style>
</head>
<body>
<div id="full"></div>
<div id="container">
<div id="other"></div>
<div id="test"></div>
</div>
<script>
var io = new IntersectionObserver((entries) => {
console.log('entries: ', entries[0].intersectionRatio);
}, {
threshold: [0, 0.5, 1],
root: document.getElementById('container')
})
io.observe(document.getElementById('test'));
</script>
</body>
</html>
在移动container容器的滚动条时,保持界面中看不到test容器,但是只要当test容器出现在container容器的可见区域时,就会触发回调函数。
如上图,虽然还没看到绿色的区域,但是此时已经触发了回调函数,container区域实际情况如下图
rootMargin
rootMargin用于扩展收缩rootBounds这个矩形的大小,从而影响交叉区域的大小,设置时传入字符串,对应于css中的”top,right,bottom,left“的设置方式,也可以使用css中的"top/bottom,left/right"的方式
var io = new IntersectionObserver((entries) => {
console.log('entries: ', entries[0].intersectionRatio);
}, {
threshold: [0, 0.5, 1],
root: document.getElementById('container'),
rootMargin: "100px 0px 0px 0px"
})
这样设置后,由于test本身就是100px,所以只有在intersectionRatio为1时才会触发回调函数。
IntersectionObserverEntry 对象
IntersectionObserverEntry 对象是构造IntersectionObserver对象时回调函数可以直接调用的参数,如上面的小试验中
var io = new IntersectionObserver((entries) => {
console.log('entries: ', entries);
})
io.observe(document.getElementById('test'));
IntersectionObserverEntry 对象属性
time
:监听器元素的持续时间
target
:被观察的目标元素,是一个 DOM 节点对象
rootBounds
:根元素的矩形区域的信息,可以用getBoundingClientRect()
方法得到,如果没有根元素(即直接相对于视口滚动),则返回null
boundingClientRect
:目标元素的矩形区域的信息
intersectionRect
:目标元素与视口(或根元素)的交叉区域的信息
intersectionRatio
:目标元素的可见比例,即intersectionRect
占boundingClientRect
的比例,完全可见时为1
,完全不可见时小于等于0
浏览器支持
看看MDN这张图,内心波澜不惊,,,
因为IE无法兼容,所以要在IE实现这些功能,还是得老老实实使用scroll事件来整。
参考自