利用Intersection Observer实现图片懒加载性能优化

news2024/11/15 17:42:11

ntersection Observer是浏览器所提供的一个 Javascript API,用于异步的检测目标元素以及祖先或者是顶级的文档视窗的交叉状态

这句话的意思就是:

我们可以看的图片当中,绿色的 target element(目标元素),并且存在一个顶层的或者祖先的文档视窗也就是当前图片中的,灰色的 browser viewport(浏览器的视窗)

当 target element(目标元素)进行移动的时候,将会与 browser viewport(浏览器的视窗)进行交叉状态的监控,那么利用这个交叉状态的监控,我们就可以实现诸如一个懒加载无限滚动或者是与元素可见性相关的一种操作。

Intersection Observer基本概念的理解:

Intersection Observer是一个观察期,创建一个观察的对象,该对象可以观察一个或多个元素,而我们的目标元素target element 则是需要被观察的 dom元素,至于 intersection ratio 也就是交叉 其目标元素 与 其祖先或视窗 相交的一个状态,那么交叉比例也就是 intersection ratio指的是目标元素与其视窗或祖先元素相交的一个百分比。我们可以从上方图片中感受到这里面如果绿色的顶部这条线和 browser viewport 的底部是重合的,我们的交叉比例应该是0;如果是图片中当前的位置,我们的交叉比例应该接近于0.5也就是百分之五十;如果在往上走的时候,我们的交叉比例可能就是1

那么利用Intersection Observer能否去实现懒加载的性能优化呢,我们需要先确认的是:为什么会需要进行性能优化、我们原来进行图片懒加载的方式又是怎样的,我们可以通过一个实例进行相应是说明:

html 代码:

利用link进行相对应的样式引入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./index2.css">
</head>
<body>
    <div>
        <h1>图片相册</h1>
        <img data-src="http://pic1.win4000.com/wallpaper/2018-09-19/5ba21a3006800.jpg" alt="">
        <img data-src="https://t7.baidu.com/it/u=1785207335,3397162108&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=338595665,4065109605&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=2581522032,2615939966&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=245883932,1750720125&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=3423293041,3900166648&fm=193&f=GIF" alt="">
        <img data-src="https://t7.baidu.com/it/u=3241434606,2550606435&fm=193&f=GIF" alt=""> 
        <img data-src="https://t7.baidu.com/it/u=1417505637,1247476664&fm=193&f=GIF" alt="">
        <img data-src="https://img0.baidu.com/it/u=775184654,1087701200&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500">
        <img data-src="https://lmg.jj20.com/up/allimg/1114/1110200ZS0/2011100ZS0-9-1200.jpg" alt="">
    </div>
    
</body>
<script src="./index2.js"></script>
</html>
css代码:
// 对页面中的img标签进行一个控制
img{
    width: 100vw;  // 宽度
    transform: translateX(50%);  // 横轴变化的操作(也就是位移)
    opacity: 0;  // 不可见
    transition: all 500ms;  // 动画的控制
} 
 
.fade{
    transform: translateX(0);  // 位移操作
    opacity: 1;  // 可见状态
    transition: all 500ms;  // 动画的操作
}
js代码:
//查询所有的img标签内容
const targets = document.querySelectorAll('img');
 
// 监听滚动事件
window.addEventListener("scroll", (event) => {
    // 遍历所有的img标签
    targets.forEach((img) => {
        // 获取img标签的top值
        console.log("load img")
        const rect = img.getBoundingClientRect().top;
        // 如果img标签的top值小于窗口的高度
        if (rect <= window.innerHeight){
            // 获取img标签的data-src属性值
            const src = img.getAttribute("data-src");
            // 将data-src属性值赋值给src属性
            img.getAttribute("src", src);
            // 添加fade类名
            img.classList.add("fade");
        }
    })
})

我们可以查看一下页面:

当我们进行滚动操作的时候,将会不断的加载显示我们所需要显示的应一个图片,但是,当我们将控制台切换到console,会发现当我们滚动滚动条时,打印的信息频率异常的高,随随便便就产生了上千次的打印代码的输出操作,这也就是意味着我们的性能其实是极其的低下的,那么如何去减少滚动时对于图片懒加载显示的性能提升呢?

我们可以去考虑,当这个图片显示在这个browser viewport(浏览器的视窗),我们对其进行的是观察操作,只有在可视区里面,我们才对图片进行处理,利用的就是Intersection Observer的操作处理。

那么利用Intersection Observer进行具体功能的实现:

//查询所有的img标签内容
const targets = document.querySelectorAll('img');
 
// 定义一个函数
const lazyload = target =>{
    // 进行实体对象entries,并且设置一个observer参数内容
    const io = new IntersectionObserver((entries,observer) =>{
        // 进行实体对象的循环(这个实体对象便是我们之后的图片)
        entries.forEach((entry)=>{  // entry:每一个实体对象
            console.log("load img")
            
            // 当图片实例内容进行到我们的观察区时(也就是交叉的一种状态)
            if(entry.isIntersecting){ 
                const img = entry.target  // 设置一个图片,便是target目标
                const src = img.getAttribute("data-src")  // 通过data-src这个自定义数据内容进行来源数据的获取属性
                img.setAttribute("src",src);  // 设置图片路径
                img.classList.add("fade")  // 添加动画效果
                observer.disconnect();  // 将观察的内容进行取消连接的一个状态
            }
        })
    })
    io.observe(target)  // 通过io进行具体的observe观察图片内容
}
 
targets.forEach(lazyload);  // 最终对图片(获取到的图片数组)进行循环,调用的则是lazyload 自定义函数

 此时,我们再进行滚动下来操作时,console打印的次数只有十几次:

而使用scroll监听滚动时,有成千次的执行,所以我们可以利用Intersection Observer进行一个图片懒加载性能优化的一个处理。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1439668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion 模型下载:Disney Pixar Cartoon Type B(迪士尼皮克斯动画片B类)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 这是我之前的模型迪士尼皮克斯卡通类型A与我自己训练的Lora在中途旅程图像上的合并结果。与之前的版本相比&#xff0c;男性和老年人看起来更像真正的皮克斯角色&a…

【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏2(附项目源码)

最终效果 文章目录 最终效果系列目录前言添加捕食者动画控制源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中&#xff0c;我们将探索如何用unity制作一个3D动物AI生态系统游戏…

内网渗透靶场02----Weblogic反序列化+域渗透

网络拓扑&#xff1a; 攻击机&#xff1a; Kali: 192.168.111.129 Win10: 192.168.111.128 靶场基本配置&#xff1a;web服务器双网卡机器&#xff1a; 192.168.111.80&#xff08;模拟外网&#xff09;10.10.10.80&#xff08;模拟内网&#xff09;域成员机器 WIN7PC192.168.…

AI嵌入式K210项目(26)-二维码识别

文章目录 前言一、什么是二维码&#xff1f;二、实验准备三、实验过程四、API接口总结 前言 本章介绍基于机器视觉实现二维码识别&#xff0c;主要包含两个过程&#xff0c;首先检测图像中是否有二维码&#xff0c;如果有则框出并打印二维码信息&#xff1b; 一、什么是二维码…

吉他学习:右手拨弦方法,右手拨弦训练 左手按弦方法

第六课 右手拨弦方法https://m.lizhiweike.com/lecture2/29362775 第七课 右手拨弦训练https://m.lizhiweike.com/lecture2/29362708

Redis——缓存设计与优化

讲解Redis的缓存设计与优化&#xff0c;以及在生产环境中遇到的Redis常见问题&#xff0c;例如缓存雪崩和缓存穿透&#xff0c;还讲解了相关问题的解决方案。 1、Redis缓存的优点和缺点 1.1、缓存优点&#xff1a; 高速读写&#xff1a;Redis可以帮助解决由于数据库压力造成…

高斯伪谱C++封装库开源!

Windows x64/86 C无依赖运行高斯伪谱法求解最优控制问题&#xff0c;你只需要ElegantGP! Author: Y. F. Zhang His Github: https://github.com/ZYunfeii 写在前面 这个库在你下载它的那一时刻起不再依赖任何其他代码&#xff0c;直接可用来构建C的最优控制问题并进行求解。…

vscode配置wsl ubuntu c++的环境

在ubuntu安装llvm/clang sudo apt install llvm clang clangd lldb vscode的调试器接口是按GDB开发的&#xff0c;所以需要一个适配器&#xff0c;lldb-mi就是这个适配器。lldb-mi原来是llvm项目的一部分&#xff0c;后面成为了一个单独的项目https://github.com/lldb-tools/…

编译原理实验1——词法分析(python实现)

文章目录 实验目的实现定义单词对应的种别码定义输出形式&#xff1a;三元式python代码实现运行结果检错处理 总结 实验目的 输入一个C语言代码串&#xff0c;输出单词流&#xff0c;识别对象包含关键字、标识符、整型浮点型字符串型常数、科学计数法、操作符和标点、注释等等。…

一条 SQL 更新语句是如何执行的?

之前你可能经常听 DBA 同事说&#xff0c;MySQL 可以恢复到半个月内任意一秒的状态&#xff0c;惊叹的同时&#xff0c;你是不是心中也会不免会好奇&#xff0c;这是怎样做到的呢&#xff1f; 我们先从一条更新语句讲起&#xff0c;首先创建一个表&#xff0c;这个表有一个主键…

百卓Smart管理平台 uploadfile.php 文件上传漏洞【CVE-2024-0939】

百卓Smart管理平台 uploadfile.php 文件上传漏洞【CVE-2024-0939】 一、 产品简介二、 漏洞概述三、 影响范围四、 复现环境五、 漏洞复现手动复现小龙验证Goby验证 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工…

Python 线性回归可视化 并将回归函数放置到图像上

import matplotlib.pyplot as plt import scipy import seaborn as sns# 加载内置的数据集 df sns.load_dataset(tips)#create regplot p sns.regplot(xtotal_bill, ytip, datadf)#calculate slope and intercept of regression equation slope, intercept, r, p, sterr sci…

FlinkSql 窗口函数

Windowing TVF 以前用的是Grouped Window Functions&#xff08;分组窗口函数&#xff09;&#xff0c;但是分组窗口函数只支持窗口聚合 现在FlinkSql统一都是用的是Windowing TVFs&#xff08;窗口表值函数&#xff09;&#xff0c;Windowing TVFs更符合 SQL 标准且更加强大…

[项目管理] 如何使用git客户端管理gitee的私有仓库

最近发现即使翻墙也无法g使用ithub了&#xff0c;需要把本地的项目搬迁到新的git托管平台。 gitee 是一个国内开源项目托管平台&#xff0c;是开源开发者、团队、个人进行 git 代码管理和协作的首选平台之一。本文将详细介绍如何向 gitee 提交私有项目。 注册 Gitee 账号并创建…

AD域国产替代方案,助力某金融企业麒麟信创电脑实现“真替真用”

近期收到不少企业客户反馈采购的信创PC电脑用不起来&#xff0c;影响信创改造的进度。例如&#xff0c;某金融企业积极响应国产化信创替代战略&#xff0c;购置了一批麒麟操作系统电脑。分发使用中发现了如下问题&#xff1a; • 当前麒麟操作系统电脑无法做到统一身份认证&…

K8S系列文章之 [使用 Alpine 搭建 k3s]

官方文档&#xff1a;K3s - 轻量级 Kubernetes | K3s 官方描述&#xff0c;可运行在 systemd 或者 openrc 环境上&#xff0c;那就往精简方向走&#xff0c;使用 alpine 做系统。与 RHEL、Debian 的区别&#xff0c;主要在防火墙侧&#xff1b;其他基础配置需求类似&#xff0…

jmeter的简单使用

1、打开jmeter 打开Jmeter 安装包&#xff0c;进入\bin 中&#xff0c;找到“ApacheJMeter.jar”或"jmeter.bat", 双击打开即可 2、建立线程组 如下图所示&#xff0c;右击TestPlan&#xff0c;点击ADD->Threads(Users)->ThreadGroup 线程组页面分析&#xf…

IS-IS 接口认证密码平滑更换

拓扑图 配置 AR1、AR2建立ISIS level-2邻居关系&#xff0c;并配置接口认证密码为huawei sysname AR1 # isis 1is-level level-2network-entity 49.0000.0000.0000.0001.00 # interface GigabitEthernet0/0/0ip address 12.1.1.1 255.255.255.0 isis enable 1isis authentica…

ThinkPHP 中使用Redis

环境.env [app] app_debug "1" app_trace ""[database] database "" hostname "127.0.0.1" hostport "" password "" prefix "ls_" username ""[redis] hostname "127.0.0.1…

【C语言】通过socket看系统调用过程

一、通过socket看系统调用过程 在Linux操作系统中&#xff0c;系统调用是用户空间与内核空间之间交互的一种方式。当一个应用程序需要执行操作系统级别的任务时&#xff0c;比如创建一个网络套接字&#xff08;socket&#xff09;&#xff0c;它必须通过系统调用请求内核来执行…