IntersectionObserverAPI 应用:图片懒加载|固定导航栏|模块渐入

参考

Udemy js教程

Intersection Observer API参考文档

概念

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指向被观察者。更多属性值可点击这里阅读参考文档

    1. 初次进入页面都会进行一个初始化,此时entries包括所有被观察者的信息。

    2. 后续只有在交叉率达到或小于阈值时,entries数组才会重置,此时entries包括达到交叉率阈值的被观察者的信息。

  • observer:观察者对象

Demo说明

该实例包含以下应用:

  1. 导航栏固定:当用户滑到第二个模块且第一个模块快消失时,导航栏固定。
  2. 模块元素渐入
  3. 图片懒加载(为了体现效果切换了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')
    })
    // ...
}
posted @ 2022-07-08 10:58  sanhuamao  阅读(219)  评论(0编辑  收藏  举报