IntersectionObserver
创建对象
var io = new IntersectionObserver(callback, option);
IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。
// 开始观察,参数是观察对象元素
io.observe(document.getElementById('example')); // 停止观察
io.unobserve(element); // 关闭观察器
io.disconnect();
如果要观察多个节点,就要多次调用这个方法。
io.observe(elementA);
io.observe(elementB);
callback 参数
目标元素的可见性变化时,就会调用观察器的回调函数callback。callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象
const intersectionObserver = new IntersectionObserver((entries) => {
console.log(entries);# entries 返回数组
for (entry of entries)
{
if (entry.intersectionRatio > )
{
addAnimationClass(entry.target, animationClass);
}
else {
console.log(animationClass); removeAnimationClass(entry.target, animationClass);
}
}
}
IntersectionObserverEntry对象一共有六个属性

- boundingClientRect:目标元素的矩形区域的信息
- intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
- intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
- rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
- target:被观察的目标元素,是一个 DOM 节点对象
- time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
Option 对象
IntersectionObserver构造函数的第二个参数是一个配置对象。它可以设置以下属性。
6.1 threshold 属性
threshold属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。
new IntersectionObserver(
entries => {/* ... */},
{
threshold: [, 0.25, 0.5, 0.75, ]
}
);
用户可以自定义这个数组。比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。
6.2 root 属性,rootMargin 属性
很多时候,目标元素不仅会随着窗口滚动,还会在容器里面滚动(比如在iframe窗口里滚动)。容器内滚动也会影响目标元素的可见性,IntersectionObserver API 支持容器内滚动。root属性指定目标元素所在的容器节点(即根元素)。注意,容器元素必须是目标元素的祖先节点。
var option = {
root: document.querySelector('.container'),
rootMargin: "500px 0px"
};
var observer = new IntersectionObserver(
callback,
option
);
上面代码中,除了root属性,还有rootMargin属性。后者定义根元素的margin,用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小。它使用CSS的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值。
这样设置以后,不管是窗口滚动或者容器内滚动,只要目标元素可见性变化,都会触发观察器。
惰性加载案例
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6"></script> -->
<title>IntersectionObserver</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
} div {
margin: 0 auto;
max-width: 100%;
width: 600px;
} #top {
height: 1200px;
background-color: #aaaaaa;
} #middle {
margin-top: 200px;
opacity: 0;
height: 400px;
background-color: #000000;
} #bottom {
height: 300px;
background-color: #333;
} #middle.move,
#bottom.move {
animation: movefromleft 2s;
animation-fill-mode: forwards;
} @keyframes movefromleft {
from {
opacity: 0;
transform: translateX(-300px);
}
to {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head> <body>
<div id="top"></div>
<div id="middle"></div>
<div id="bottom"></div>
</body>
<script>
window.onload = (event) => {
const middle = document.getElementById('middle'),
bottom = document.getElementById('bottom');
const animationClass = 'move';
// 创建监听
const intersectionObserver = new IntersectionObserver((entries) => {
console.log(entries);
for (entry of entries) {
if (entry.intersectionRatio > 0) {
addAnimationClass(entry.target, animationClass);
} else {
console.log(animationClass);
removeAnimationClass(entry.target, animationClass);
}
}
});
// 添加动画class的操作
function addAnimationClass(elem, animationClass) {
elem.className.includes(animationClass) ? 1 : elem.className = elem.className + ' ' + animationClass;
}
// 移除动画class的操作
function removeAnimationClass(elem, animationClass) {
elem.className.includes(animationClass) ? elem.className = elem.className.replace(animationClass, '') : 1;
console.log(elem.className);
}
// 开启监听
intersectionObserver.observe(middle);
intersectionObserver.observe(bottom);
} </script> </html>
单个元素(图片)
const eles = document.querySelectorAll('img[data-src]')
const observer = new IntersectionObserver( entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
let oImg = entry.target
oImg.src = oImg.getAttribute('data-src')
observer.unobserve(oImg)
}
})
}, {
root: document.getElementById('list')
})
eles.forEach(item => { observer.observe(item) })
多个图片(元素)
注意:
IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。
规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。
文章引用:IntersectionObserver API 使用教程
IntersectionObserver的更多相关文章
- IntersectionObserver API
温馨提示:本文目前仅适用于在 Chrome 51 及以上中浏览. 2016.11.1 追加,Firefox 52 也已经实现. 2016.11.29 追加,Firefox 的人担心目前规范不够稳定,未 ...
- 使用IntersectionObserver更高效的监视某个页面元素是否进入了可见窗口
比如说,你想跟踪 DOM 树里的一个元素,当它进入可见窗口时得到通知. 也许想实现即时延迟加载图片功能,或者你需要知道用户是否真的在看一个广告 banner. 你可以通过绑定 scroll 事件或者用 ...
- IntersectionObserver实现图片懒加载
API: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API 直接上源码: <!DOCTYPE ...
- IntersectionObserver API 使用教程
转载:原文地址:http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html 网页开发时,常常需要了解某个元素是否进入了&q ...
- IntersectionObserver简介
写在前面 在移动端,有个很重要的概念,叫做懒加载,适用于一些图片资源特别多,ajax数据特别多的页面中,经常会有动态加载数据的场景中,这个时候,我们通常是使用监听scroll或者使用setInterv ...
- [Javascript] IntersectionObserver -- Lazy Load Images on a Website
When it comes to websites performance is king. How long it takes for a page to load can mean the dif ...
- IntersectionObserver API,观察元素是否进入了可视区域
网页开发时,常常需要了解某个元素是否进入了"视口"(viewport),即用户能不能看到它. 上图的绿色方块不断滚动,顶部会提示它的可见性. 传统的实现方法是,监听到scroll事 ...
- 谈谈IntersectionObserver懒加载
概念 IntersectionObserver接口(从属于Intersection Observer API)为开发者提供了一种可以异步监听目标元素与其祖先或视窗(viewport)交叉状态的手段.祖 ...
- js IntersectionObserver api
API const options = { root: null, threshold: [0, 0.5, 1], rootMargin: '30px 100px 20px' } var io = n ...
随机推荐
- php 读取和下载execl
最近用到php 对excel 的操作 下来 小弟为大家 先贴一下自己的代码 有什么补充的 大神们请指点下.感激不尽. 我用的是yii2 yii2中有类 phpexcel 先说说下载吧. 首先下载 ...
- SqlServer try catch 捕获不到的一些错误及解决方法
IF (OBJECT_ID('AA','U') IS NOT NULL) DROP TABLE AA CREATE TABLE AA(ID INT) SELECT * FROM AA --注:数据库当 ...
- java容器 Map Set List
容器:在java中,如果有一个类专门用来存放其他类的对象,这个类就叫做容器,或者叫集合,集合就是将若干性质相同或者相近的类的对象组合在一起而形成一个整体. boolean add(Object obj ...
- zend studio永久使用的方法
安装时选择试用版,以后每天的剩余天数会减少,找到c盘->用户->administrator删除三个文件(.zend,.zend studio,.zs)即可,.zs往往是隐藏的,这时需要选择 ...
- Reportng 的测试报告在 Jenkins 中显示不全
通过Jenkins执行接口测试生成测试报告,用Jenkins的web服务打开html显示不全. 环境: Jenkins版本:1.651.2 Jenkins发布在mac上面 使用的是testng管理测试 ...
- Sql语句摘要
1.分批更新数据库 declare @x intset @x=1 while(@x<=51) begin begin tran update UserFavorite set UserFavor ...
- javascript总结16:数组array12
1 Array 对象 作用:Array 对象用于在变量中存储多个值. 1.1 数组定义 var ary = new Array();//通过创建对象的方式创建数组 var ary1 = [];// 直 ...
- 编写高质量代码改善C#程序的157个建议——建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理
建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理 在标准的Dispose模式中,我们注意到一个以~开头的方法,如下: /// <summary> /// 必须,防止程序员忘记 ...
- c++基础之引用reference
1.何为引用 简单来说就是,比如你换了个新名字,用新名字叫你,你也会答应 2.引用vs指针 -引用没有null,好比你说你换了个新名字,但是新名字是啥总得有点东西 -一旦引用被初始化后就不可以指到另外 ...
- 关于hibernate的查询
为什么建议hibernate查询全部字段 一般而言,要查询什么字段就查询什么字段,不要select * from表,但是在hibernate,我们其实可以不遵循这个规则,建议我们把所有属性都查询出来( ...