IntersectionObserverAPI 应用:图片懒加载|固定导航栏|模块渐入
参考
概念
Intersection Observer API
通过注册观察者,可以观察目标元素与可视窗口的交叉比率,当达到某一个比例时执行回调函数。它不需要一直监听滚动事件就可以做到图片懒加载、固定导航栏、滑到某个位置加入渐入动画等效果。
(源码地址)。可滑至下方查看本demo的简单说明
样例与解释
// 配置信息
const options={
root: null,
threshold: 0.1,
}
// 回调函数
const callback=(entries,observer)=>{
const [entry] = entries
if (!entry.isIntersecting) return
// ...进行一些操作
observer.unobserve(entry.target)
}
// 实例化观察者
const observer = new IntersectionObserver(callback, options)
// 观察目标元素
const targetElement=document.getElementById('target')
observer.observe(targetElement)
1.实例化观察者
接收回调函数与配置信息进行实例化:
const observer = new IntersectionObserver(callback, options)
调用观察者的observe()
方法来观察目标元素:
const targetElement=document.getElementById('target')
observer.observe(targetElement)
后续可以通过unobserve()
方法取消观察
2.配置信息
const options={
root: null,
threshold: 0.1,
}
- root:指定目标元素的某个父元素,为null时表示为浏览器视窗。用于检查目标元素的可见性。
- threshold:交叉比率阈值。当目标元素与root元素的交叉比率达到该值时会调用回调函数。
- rootMargin:控制 root 元素每一边的收缩或者扩张,默认为0。
3.回调函数
当root元素与目标元素的交叉率达到阈值时触发。此外,初次进入页面会自动触发一次。(即使交叉率没有达到阈值也会触发)
const callback=(entries,observer)=>{
const [entry] = entries
if (!entry.isIntersecting) return
observer.unobserve(entry.target)
}
-
entries:是一个数组,里面每个元素记录了root元素与被观察者的交叉变化。每个元素都是一个对象,其中
isIntersecting
返回一个布尔值,用于判断root元素与目标元素是否相交(是否达到交叉率的阈值);target
指向被观察者。更多属性值可点击这里阅读参考文档。-
初次进入页面都会进行一个初始化,此时entries包括所有被观察者的信息。
-
后续只有在交叉率达到或小于阈值时,entries数组才会重置,此时entries包括达到交叉率阈值的被观察者的信息。
-
-
observer:观察者对象
Demo说明
该实例包含以下应用:
- 导航栏固定:当用户滑到第二个模块且第一个模块快消失时,导航栏固定。
- 模块元素渐入
- 图片懒加载(为了体现效果切换了3g网络):当用户没有滑到对应图片时使用低像素图片,当滑到对应图片时加载高像素图片
一 渐入效果
观察每个section
const allSelections = document.querySelectorAll('section')
allSelections.forEach((element) => {
element.classList.add('section--hidden') //初始时这些元素是看不到的
element.style.transition = '.5s ease .5s' // 添加一个样式过渡
sectionsObserver.observe(element) //观察section
})
原始的的样式是透明并且有所偏移
.section--hidden {
opacity: 0;
transform: translateY(8rem);
}
二 固定导航栏
观察的是欢迎光临下面的容器,判断它与窗口的交叉率
// 装sections的容器
const container = document.querySelector('.container')
stickyObserver.observe(container)
回调函数:
const stickyNav = (entries, observer) => {
const [entry] = entries
// 没有交叉时导航栏不需要固定;有交叉时导航栏固定
if (!entry.isIntersecting) {
nav.classList.remove('sticky')
} else {
nav.classList.add('sticky')
}
}
.sticky {
position: fixed;
width: 100%;
z-index: 99;
}
三 图片懒加载
1.dataset
使用了数据属性用于存储图片链接
<img src="imgs/first_lazy.jpg" data-src="imgs/first.jpg"/>
说明:
// 注册属性[1]
在标签上`data-[属性名]=属性值`。属性名不能包含大写,若需要大写需要通过`-`隔开
<img src="" data-version-number="3.0"/>
// 注册属性[2]
img.dataset.versionNumber="3.0"
// 获取属性
img.dataset.versionNumber
2.模糊样式
.lazy_img {
filter: blur(10px);
}
3.load事件
切换图片地址是需要使用load
进行监听,等图片加载完毕之后再清除模糊样式
// 回调函数:
const lazyImage = (entries, observer) => {
// ...
entry.target.src = entry.target.dataset.src
entry.target.addEventListener('load', () => {
entry.target.classList.remove('lazy_img')
})
// ...
}