首页 > 其他分享 >图片懒加载不完全指南

图片懒加载不完全指南

时间:2024-04-14 14:57:11浏览次数:13  
标签:指南 function lazy lazyImage 元素 加载 图片

图片懒加载不完全指南

菜菜 菜菜 菜鸡   1 人赞同了该文章

图片懒加载

在日常开发中,我们常用的两种图片加载方式如下:

  • 使用 img 标签加载图片;
  • 使用 css background 加载图片。

在这篇文章中,您将了解如何延迟加载这两种类型的图像。

img 标签图片懒加载

对于 img 标签,我们有三个延迟加载方案,同时也可以组合使用以实现跨浏览器的最佳兼容性:

  • 使用浏览器提供的 API:loading="lazy"
  • 使用 Intersection Observer
  • 使用 scroll 和 resize 事件进行处理

使用浏览器级别的懒加载

Chrome 和 Firefox 都支持使用 loading 属性的延迟加载。把此属性添加到 <img> 元素并设置其值为 lazy 相当于告诉浏览器,如果图像在可视区域中,就立即加载它,反之则不加载。

至于加载的视口距离阈值,目前是没办法修改的,chrome 会根据当前的网络情况设置对应的阈值。

对于2020 年 7 月以后的 chrome版本,4G 网络下的视口距离阈值是 1250 像素,3G 网络下是 2500 像素。

需要注意的是我们也需要手动指定图片的宽高,否则我们可能会看到布局发生偏移。一个完整的代码实例如下:

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

demo 如下:

loading=lazy demo

有关浏览器支持的详细信息,可以参阅MDN的浏览器兼容性表。如果浏览器不支持延迟加载,那么该属性将被忽略,图像将像往常一样立即加载。

个人觉得它的缺点或者不够好的地方有以下几点:

  1. 不能自定义加载的视口距离阈值;
  2. 官方建议首屏内的图片不设置 loading="lazy" , 这需要一些额外的使用成本;
  3. 无法设置加载中情况下的占位图;
  4. 暂时没有对应的 polyfil,需要我们自己结合下面介绍的两种方式之一组合使用。

有关 loading 属性更详细的内容请阅读这篇文章

使用 Intersection Observer

我们需要使用 JavaScript 来判断图片是否在视图中,如果是,则将真实的 url 地址填充到图片的 src 中。如果之前了解过延迟加载,可能我们想到的是通过 scroll 事件来判断图片是否达到可视条件。虽然这种方法是兼容性最好的,但现代浏览器提供了一种性能更高、效率更高的方法:通过 Intersection Observer API 来完成检查元素可见性的工作。

相比于依赖各种事件处理程序的实现方式,Intersection Observer 更易于使用和阅读,因为您只需注册一个观察者即可观察元素,而无需编写繁琐的元素可见性检测代码。剩下要做的就是决定当元素可见时要做什么。

它的语法如下:

const observer = new IntersectionObserver(callback, options)
// options 支持以下选项:
// {
//  root: null,  // 所监听对象的具体根元素。如果未传入值或值为null,则默认使用顶级文档的视窗。
//  rootMargin: "30px 100px 50px", // 可以简单理解为增大根元素的范围,用来修改可见的触发范围
// thresholds: [0, 0.5, 1], // 用来指定交叉比例,决定什么时候触发回调函数,是一个数组,默认是[0]。
   // 上面代码,我们指定了交叉比例为0,0.5,1,当观察元素img0%、50%、100%时候就会触发回调函数
// }

假设我们有如下图片元素:

<img 
    class="lazy" 
    src="placeholder-image.jpg" 
    data-src="image-to-lazy-load-1x.jpg" 
    data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" 
    alt="I'm an image!"
>

我们需要关注以下三点:

  1. class 属性,我们用来获取所有需要懒加载的图片元素;
  2. src 属性,引用占位图片;
  3. data-src 和 data-srcset 属性,它们是占位符属性,包含元素在进入可视区后将加载的图像的 URL。

接下里我们看如何使用Intersection Observer 来实现懒加载:

// 1. 在DOMContentLoaded事件触发时,获取所有需要懒加载的 img 标签。
document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  // 2. 如果IntersectionObserver可用,创建一个新的观察者,
  // 当 img.lazy 元素进入视口时运行回调
  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // 不支持IntersectionObserver环境下的 fallback
  }
});

使用事件进行处理

如果浏览器不支持上面所说的Intersection Observer,最简答的办法就是使用它的 polyfill,或者回退到使用 scrollresize和可能用到的orientationchange事件配合getBoundingClientRect方法来确定元素是否在可视区域中。

实现的思路如下:假设与之前的 img 标签示例相同,我们还是使用 lazy 这个 class 来获取要懒加载的图片元素,使用 setTimeout 和 active 标记 来做节流,当一个元素加载之后,将其从列表中移除。当整个需要懒加载的列表都被清空后,移除对事件的监听。示例代码如下:

document.addEventListener("DOMContentLoaded", function() {       
  let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));       
  let active = false;

  const lazyLoad = function() {
    if (active === false) {
      active = true;

      setTimeout(function() {
        lazyImages.forEach(function(lazyImage) {
          if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") {
            lazyImage.src = lazyImage.dataset.src;
            lazyImage.srcset = lazyImage.dataset.srcset;
            lazyImage.classList.remove("lazy");

            lazyImages = lazyImages.filter(function(image) {
              return image !== lazyImage;
            });

            if (lazyImages.length === 0) {
              document.removeEventListener("scroll", lazyLoad);
              window.removeEventListener("resize", lazyLoad);
              window.removeEventListener("orientationchange", lazyLoad);
            }
          }
        });

        active = false;
      }, 200);
    }
  };

  document.addEventListener("scroll", lazyLoad);
  window.addEventListener("resize", lazyLoad);
  window.addEventListener("orientationchange", lazyLoad);
});

css background 图片懒加载

和 img 标签实现方式类似,我们可以使用 JS 来判断元素是否可见,然后更改元素的 class 来实现。

举个简单的例子:

// index.css
.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

 

// lazy-background.js
document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

 

参考文章

The Complete Guide to Lazy Loading Images

标签:指南,function,lazy,lazyImage,元素,加载,图片
From: https://www.cnblogs.com/sexintercourse/p/18134149

相关文章

  • C#使用PaddleOCR进行图片文字识别
    PaddlePaddle介绍✨PaddlePaddle(飞桨)是百度开发的深度学习平台,旨在为开发者提供全面、灵活的工具集,用于构建、训练和部署各种深度学习模型。它具有开放源代码、高度灵活性、可扩展性和分布式训练等特点。PaddlePaddle支持端到端的部署,可以将模型轻松应用于服务器、移动设备和边缘......
  • JavaScript判断图片是否已经加载完毕的方法汇总_javascript技巧
    JavaScript判断图片是否已经加载完毕的方法汇总_javascript技巧 在网上有很多关于判断图片是否已经加载完毕的文章,但是有的浏览器并不适合,下面小编给大家分享一些有关JavaScript判断图片是否已经加载完毕方法汇总,具体内容如下所示:一.onload事件通过监听图片的onload事件,可......
  • React.js 网站开发:实现滚动加载动画
    React.js网站开发:实现滚动加载动画极客前端探索者前沿技术的探索者,编码艺术的实践者 最近在开发官网的过程中,涉及到UI动画的制作,其中滚动效果的使用比较频繁,特此整理一下,以便查询和温习。平滑向上过渡动画这种往下滚动过渡渐变显示的动画是最常......
  • 洛谷题单指南-数学基础问题-P1069 [NOIP2009 普及组] 细胞分裂
    原题链接:https://www.luogu.com.cn/problem/P1069题意解读:一个数s代表细胞经过一天分裂的个数,则经过t天后个数为st,要计算经过几天后能整除m1m2,也就是st%m1m2==0,有多个s,要计算天数最少就可以满足条件的。解题思路:直接求st%m1m2显然不可取,会超出整数最大范围,高精度也不是好......
  • 图像框切换图片-极语言
    比如我有两张图片3.bmp、4.bmp。 程序代码如下:程序段窗体消息(窗口,消息,参数,数据)判断(消息)为窗口关闭停止为单击左键{左键点击(参数)}处理窗口(窗口,消息,参数,数据)结束程序段窗体启动结束程序段按钮2_点击整数图片1=加载图像(0,"3.bmp",......
  • SpringBoot使用 nacos 会默认加载项目名配置文件
    问题描述boostrap.yml配置如下spring:application:name:cnblogscloud:nacos:config:server-addr:http://ip:8848namespace:d8b0df04-aa58-4a5b-b582-7d133b9e8b2c#命名空间IDfile-extension:yamlusern......
  • typora上传图片问题
    typora上传博客园教程来源https://www.bilibili.com/video/BV1Rv4y1Y7KH/?spm_id_from=333.337.search-card.all.click&vd_source=66ac5da514fe1be9729ebba538a11951下载工具链接:https://pan.baidu.com/s/1e1iVqoA7vAsBT8lir11z2Q?pwd=5axe提取码:5axe配置步骤开启控制面板-......
  • Python程序员Visual Studio Code指南5调试
    5调试当运行程序时终端输出错误时,可以参考编辑器中的"问题"面板来解决遇到的问题。不过,并非所有错误都会导致错误。可能出现的情况是,程序执行成功,但输出结果与预期不同。出现这种情况时,下一步就是找出程序中的错误。这个过程被称为调试。您可以尝试通过注释代码行(从而禁止代码......
  • 绿色免费的全景图片360查看器 - 附下载地址
    在数字化的时代,360全景图片以其独特的视角和沉浸式体验,正在逐渐成为新的趋势。这些图片通常是由多张照片拼接而成,它们的长宽比通常为2:1,能够提供一个全方位的视觉享受。然而,要想真正体验这些全景图片的魅力,需要借助专门的查看器。传统的图片查看器只能展示静态的图像,而全景图片包......
  • Qt程序加载Qt platform plugin 'xcb' 出错问题解决
    1.Qt程序运行环境ubuntu16.04Qt5.12.3Qt可执行程序编译后运行Qt可执行程序后出现报错报错内容:qt.qpa.plugin:CouldnotloadtheQtplatformplugin"xcb"in""eventhoughitwasfound.ThisapplicationfailedtostartbecausenoQtplatformplugincouldbe......