我们经常遇到这样的需求——检测一个元素是否可见或者两个元素是否相交,如
返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
缺点:事件监听和调用都是在主线程上运行,因此频繁触发、调用,造成浏览器频繁的重绘和回流,给网站带来相当大的卡顿
window对象上有一个Intersection Observer API,
它会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时 (或者 viewport ),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行。这样,我们网站的主线程不需要再为了监听元素相交而辛苦劳作,浏览器会自行优化元素相交管理。
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
//回调函数只会在元素达到thresholds 规定的阈值时才会执行。
let observer = new IntersectionObserver(callback, options);
属性 | 说明 |
---|---|
root | 必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。 |
rootMargin | 用作 root 元素和 target 发生交集时候的计算交集的区域范围 |
threshold | 目标 (target) 元素与根 (root) 元素之间的交叉比 (intersection ratio)取值在 0.0 和 1.0 之间。可以是单一的 number 也可以是 number 数组,默认值是 0 (意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为 1.0 含义是当 target 完全出现在 root 元素中时候 回调才会被执行。 |
let callback =(entries, observer) => {
entries.forEach(entry => {
// entry.boundingClientRect 返回包含目标元素的边界信息
//entry.rootBounds 返回根元素的边界信息
// entry.intersectionRatio. 返回intersectionRect 与 boundingClientRect 的比例值。
// entry.intersectionRect. 用来描述根和目标元素的相交区域。
// entry.isIntersecting
//返回一个布尔值,如果目标元素与根相交,则返回true. 如果返回false, 变换是从交叉状态到非交叉状态。
// entry.target 与根出现相交区域改变的元素
});
};
let target = document.querySelector('#listItem');
observer.observe(target);
//unobserve() 停止监听特定目标元素
请留意,你注册的回调函数将会在主线程中被执行。所以该函数执行速度要尽可能的快。如果有一些耗时的操作需要执行,建议使用 Window.requestIdleCallback() 方法
observer.unobserve(target);//例如图片懒加载时,加载完后即停止监听该元素
observer.disconnect();
1. IntersectionObservers中的回调是在主线程中运行的,数据是异步传递的,这意味着我们的回调函数的调用优先级是比较低的,要等到浏览器空闲时。因此使用此api完成类似滚动相关的动画注定失败,因为数据在你使用它的时候已经过时了。
IntersectionObservers deliver their data asynchronously, and your
callback code will run in the main thread. Additionally, the spec
actually says that IntersectionObserver implementations should use
requestIdleCallback(). This means that the call to your provided
callback is low priority and will be made by the browser during idle
time. This is a conscious design decision
2.api只是告诉我们元素什么时候进入视窗中,但是它没告诉我们
元素是否被页面其他内容挡住了,或者元素的可视display是否被改成了其他效果
or whether the Element’s visual display has been modified by any visual effects (transform, opacity, filter, etc)
参考链接:
https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect
https://web.dev/intersectionobserver-v2/
https://developer.chrome.com/blog/intersectionobserver/#what-is-intersectionobserver-not-about