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 ...
随机推荐
- json_encode和json_decode和isset和array_key_exists
1.json_decode() json_decode — 对 JSON 格式的字符串进行编码 说明 mixed json_decode ( string $json [, bool ...
- Log4j配置很详细
来自: http://www.blogjava.net/zJun/archive/2006/06/28/55511.html Log4J的配置文件(Configuration File)就是用来设置记 ...
- 31.SUM() 函数
SUM() 函数 SUM 函数返回数值列的总数(总额). SQL SUM() 语法 SELECT SUM(column_name) FROM table_name SQL SUM() 实例 我们拥有下 ...
- nodelet的理解
1.介绍 nodelet包可以为在相同进程中的多个算法之间实现零拷贝的传输方式. 这个包也提供了实现一个nodelet所需的nodelet基类以及用于实例化nodelet的NodeletLoader类 ...
- spark源码阅读之network(3)
TransportContext用来创建TransportServer和TransportclientFactory,同时使用TransportChannelHandler用来配置channel的pi ...
- [GO]工程管理
同级目录: 1.分文件编程,多个源文件,必须放在src目录 2.设置GOPATH目录,目录地址不包括src后缀 3.同一个目录,包名必须一样 4.go env查看go相关的环境路径 5.同一个目录,调 ...
- phpmyadmin安全预防
头疼的安全 之前服务器总是本人黑,千疮百孔,只能一步步的去做一些安全防范,如何防范自然先从如何渗透开始. 文章及建议 前段时间看到了个phpmyadmin提权的教程,很多人都说现在那里还有root帐号 ...
- 编写高质量代码改善C#程序的157个建议——建议55:利用定制特性减少可序列化的字段
建议55:利用定制特性减少可序列化的字段 特性(attribute)可以声明式地为代码中的目标元素添加注释.运行时可以通过查询这些托管块中的元数据信息,达到改变目标元素运行时行为的目的.System. ...
- JS 换行写法
var populatePullUpHtml = function (id) { var html = '<div id="' + id + '" class="' ...
- C#开源网络通信库PESocket的使用
PESocket PESocket开源项目GitHub地址:点击跳转 基于C#语言实现的高效便捷网络库.支持集成到Unity当中使用. 不用过多了解网络通信内部原理,只需几行简单的代码,便能简捷快速开 ...