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 ...
随机推荐
- 【总结整理】原创概念原创idea---摘自《结网》
假如你有一个原创想法,搜索引擎是否已有现成产品与自己的想法一致,如果有,研究他可以节省很多摸索的时间:若没有,那就是一个货真价实的原创idea: 第一类:受到现有产品的启发,将既有概念进行了转换. 第 ...
- EKF model&realization
REF: https://pythonrobotics.readthedocs.io/en/latest/modules/localization.html#unscented-kalman-filt ...
- 27-拓扑排序-poj1094
http://poj.org/problem?id=1094 Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Su ...
- 62-U型数字
https://nanti.jisuanke.com/t/20683 #include <iostream> using namespace std; int main(){ int ct ...
- Docker学习之路(一)
容器简介 管理程序虚拟化(hypervisor virtualization, HV)是通过中间虚拟运行于物理硬件之上.而容器是直接运行在操作系统内核之上用户空间.因此,容器虚拟化运行也成为“操作系统 ...
- 模板模式和Comparable类
模板模式中,父类规定好了一些算法的流程,并且空出一些步骤(方法)留给子类填充 Java的数组类中静态方法sort()就是一个模板,它空出了一个compareTo的方法,留给子类填充,用来规定什么是大于 ...
- Installing XGBoost on Mac OSX
0. Get gcc with open mp. Just paste and execute the following command in your terminal, once Home ...
- [原创]MongoDB C++ 驱动部分问题解决方案(MongoDB C++ Driver)
本文为我长时间开发以及修改MongoDB C++ Driver时的一些问题和解决方案.目前本文所介绍的相关引擎也已经发布闭源版本,请自行下载 库版本以及相关位置:http://code.google. ...
- hibernate使用记录
1.执行SQL语句而非hql语句,getSession().createQuery(sql2) 执行的是hibernate语句; Query query2 = this.onlineMonitorDa ...
- c#事务的使用、示例及注意事项
什么是数据库事务 数据库事务是指作为单个逻辑工作单元执行的一系列操作. 设想网上购物的一次交易,其付款过程至少包括以下几步数据库操作: · 更新客户所购商品的库存信息 · 保存客户付款信息--可能 ...