IntersectionObserver:ES6新的监听器API,能够监听一个或者多个盒子和浏览器可视窗口的交叉信息,只要盒子和可视窗口的交叉信息发生变化,则监听器就会被触发,我们可以做一些自己想做的事情
一、API
IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点
//let ob = new IntersectionObserver(callback, option);
let ob = new IntersectionObserver(callback,{
//控制一露头算交叉状态改变0 默认为0 还是完全出现才算交叉状态改变1
threshold:[1]
//thresholds属性值为[0, 0.25, 0.5, 0.75, 1]
})
// 监听DOM元素
ob.observe(document.querySelector('#box'));
// 移除监听
ob.unobserve(element);
上面代码中,observe的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。
ob.observe(elementA);
ob.observe(elementB);
二、callback 参数
目标元素的可见性变化时,就会调用观察器的回调函数callback
。<br />
let ob = new IntersectionObserver(changes => {
// 触发:
// + 监听DOM元素后触发一次
// + 刚一进入视口 触发一次
// + 完全离开视口 触发一次
console.log(changes);
});
上面代码中,回调函数采用的是箭头函数的写法。callback函数的参数(changes)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,changes数组就会有两个成员。
参数是个数组,即 changes=[…] ,数组中的每一项都是监听的元素的交叉信息,但可以循环绑定多次元素
示例:瀑布流案例中,一次只能监听一种元素(img),但img有多个,所以数组中每一项就是对应的交叉信息
let ob=new IntersectionObserver(changes=>{
// 循环每个盒子监听到的交叉盒子,把出现在视口中的盒子做延迟加载
changes.forEach(change=>{
let{isIntersecting,target}=change;
// target监听的盒子
//isIntersecting 为 true 则是显示在了视口中
// console.log(change);
if(isIntersecting){
// 当前盒子已经出现在视口中 target监听的盒子
singleImgLazy(target.querySelector('img'));
// 处理后 ,这个盒子就没必要再监听了
ob.unobserve(target);
}
});
},{
// 控制完全出现在视口中 才算交叉状态改变
threshold:[1]
});
三、IntersectionObserverEntry 对象
IntersectionObserverEntry对象提供目标元素的信息每个属性的含义如下。
- target:监听的这个DOM元素对象
- boundingClientRect:元素和可视窗口的交叉信息
- isIntersecting:false 记录当前元素是否出现在可视窗口中(默认一露头就算)
<!DOCTYPE html>
<html>
<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>IntersectionObserver</title>
<link rel="stylesheet" href="css/reset.min.css">
<style>
html,
body {
height: 200%;
background: -webkit-linear-gradient(top left, pink, orange);
}
#box {
position: absolute;
left: 200px;
top: 800px;
width: 100px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
let box = document.querySelector('#box');
/* let ob = new IntersectionObserver(changes => {
// 当监听的元素和可视窗口交叉信息发生改变的时候触发执行
// + changes记录每一个被监听的元素和可视窗口的交叉信息(数组)
// 每一项记录的信息
// boundingClientRect:{...} 元素和可视窗口的交叉信息
// isIntersecting:false 记录当前元素是否出现在可视窗口中(默认一露头就算)
// target:... 监听的这个DOM元素对象
// 触发:
// + 监听DOM元素后触发一次
// + 刚一进入视口 触发一次
// + 完全离开视口 触发一次
console.log(changes);
});
// 监听DOM元素 unobserve就是移除监听
ob.observe(box); */
let ob = new IntersectionObserver(changes => {
// 交叉状态改变,就会被触发执行
console.log(changes);
}, {
// 控制一露头算交叉状态改变0 还是完全出现才算交叉状态改变1
threshold: [1]
});
ob.observe(box);
</script>
</body>
</html>