首页 > 其他分享 >图片懒加载

图片懒加载

时间:2023-01-30 22:33:26浏览次数:55  
标签:function clientHeight window offsetTop 加载 图片

前言

影响网页性能最主要的因素应该属图片资源了,现在一张图片动不动几兆,如果一张页面有很多图片(像电商类网站),等页面上的图片全部加载完毕再显示在浏览器上的话,用户可能早就不耐烦地关掉网页了。解决该问题的办法就是图片懒加载了,即只有用到的时候再加载图片,避免无意义的开销。

懒加载是一个理念,具体的应用场景不止一个:

  1. 优先加载可视区域的内容,其它部分等进入了可视区域再加载;
  2. 在单页应用中,未显示的tab页不加载图片;

我们讨论的是场景1,对于场景2,其实vue这些组件化方案已经默认处理掉了。

原理解析

一张图片是否加载,是由其是否具有src属性决定的,没有src属性时,浏览器就不会发起图片加载请求。这是我们实现图片懒加载的切入点。

接下来我们来解决如何判断当前图片是否已经在可视区域中的问题。这里要用到几个API:

  • document.documentElement.clientHeight:获取屏幕可视区域的API(包含内边距,不包含水平滚动条、边框和外边距);
  • document.documentElement.scrollTop:获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离。
  • element.offsetTop:获取元素相对于文档顶部的高度;

img

图片来自参考资料1

根据上图我们可以很快地知道,当满足offsetTop-scrollTop<clientHeight的时候,就可以加载图片了。

代码实现

img {
  display: block;
  width: 100%;
  height: 300px;
  margin-bottom: 20px;
}
<img data-src="./images/1.jpg" alt="">
<img data-src="./images/2.jpg" alt="">
<img data-src="./images/3.jpg" alt="">
<img data-src="./images/4.jpg" alt="">
<img data-src="./images/5.jpg" alt="">
<img data-src="./images/6.jpg" alt="">
<img data-src="./images/7.jpg" alt="">
<img data-src="./images/8.jpg" alt="">
<img data-src="./images/9.jpg" alt="">
<img data-src="./images/10.jpg" alt="">
<img data-src="./images/1.jpg" alt="">
<img data-src="./images/2.jpg" alt="">
// 文档加载完毕时注册懒加载功能
window.onload = lazyLoad;

// 给所有的图片加上懒加载功能
function lazyLoad() {
  // 图片信息列表,列表元素的格式为(offsetTop, imageSrc, dom)
  const imageMetaList = [];
  // 初始化imageMetaList
  const images = document.getElementByTagName('img');
  for(let i=0; i<images.length; i++) {
    let dom = images[i];
    let offsetTop = getOffsetTop(image);
    let imageSrc = dom.getAttribute('data-src');
    imageMetaList.push({
      offsetTop, // 保存offsetTop,避免每次都要去重新计算
      imageSrc,
      dom
    })
  }
  // 获取视口的高度
  const clientHeight = document.documentElement.clientHeight;
  // 注册滚动监听
  window.onscroll = function() {
    const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    imageMetaList.forEach(imageMeta=>{
      if(imageMeta.offsetTop - scrollTop < clientHeight) {
        imageMeta.dom.src = imageMeta.imageSrc
      }
    });
  }
}

// 获取元素的offsetTop
function getOffsetTop(e) {
  let result = 0;
  while(e !== undefined) {
    result += e.offsetTop;
    e = e.offsetParent; //offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
  }
  return result;
}

改进1

js中还有一个更好的API:

  • getBoundingClientRect():返回元素的大小以及其相对于视口的位置。

有了这个API之后,我们可以用如下方式来判断图片是否进入视口:

function isInVisualArea(el) {
  var bound = el.getBoundingClientRect();
  var clientHeight = window.innerHeight;
  return bound.top <= clientHeight;
} 

有了这个方法之后,就不需要像上面的实现一样加一个缓存列表了。新的实现如下:

// 文档加载完毕时注册懒加载功能
window.onload = lazyLoad;

// 给所有的图片加上懒加载功能
function lazyLoad() {
  const images = document.getElementByTagName('img');
  // 获取视口的高度
  const clientHeight = document.documentElement.clientHeight;
  // 注册滚动监听
  window.onscroll = function() {
    images.forEach(image=>{
      if(isInVisualArea(image)) {
        image.src = image.getAttribute('data-src');
      }
    });
  }
}

// 判断是否在可视区域
function isInVisualArea(el) {
  var bound = el.getBoundingClientRect();
  var clientHeight = window.innerHeight;
  return bound.top <= clientHeight;
} 

改进2

onscroll的触发频率非常高,如果每次触发onscroll都去检查是否要加载图片比较吃性能,可以考虑加入节流机制,减少开销。

使用lazysizes

下载:

cnpm install lazysizes -S

引入:

import 'lazysizes'; // 导入插件
import 'lazysizes/plugins/parent-fit/ls.parent-fit'; // 注意:切勿从npm包中导入/获取* .min.js文件

使用:

<img 
     class="lazyload" 
     data-src='https://placehold.it/600x300//f00?text=BaymaxCSDN 1-懒加载' 
     alt=''/>

如果担心禁用JavaScript,可以结合noscript使用:

<!-- noscript pattern -->
<noscript>
	<img src="image.jpg" />
</noscript>
<img src="transparent.jpg" data-src="image.jpg" class="lazyload" />

更多的功能,如响应式图片、模糊图形、透明图形、加载动画等,见参考资料1。

使用vue-lazyload

npm install vue-lazyload -S
<img v-lazy="src"/>

参考资料

  1. 原生js实现图片懒加载
  2. lazysizes.js 图片懒加载的使用方法详解

标签:function,clientHeight,window,offsetTop,加载,图片
From: https://www.cnblogs.com/hdxg/p/17077447.html

相关文章

  • antdvue 上传图片最多四张,有预览删除
    <template><divref="classReview"><a-modal:body-style="modalStyle":confirm-loading="confirmLoading":footer="null":getConta......
  • 05-DALVIK加载和解析DEX过程
    5.1 dex和odex文件结构和关系      上图是Dex文件和Odex文件的结构和关系图。    应用程序在第一次启动app的时候,会在/dalvik/dalvik-cache目录下生成odex......
  • 用python实现一个自动保存复制图片的功能
    由于经常写作,需要为文章准备一些配图,通常这些配图是从百度图片搜索里准备的。在准备图片时,我遇到了两个小麻烦:有些图片的格式是webp,需要在另存为时指定格式有些图片需要剪切......
  • Cesium:文字转图片,图片贴到多边形上
    JS前端文字转图片:link缺点:需要在网页中有一个canvas。canvas.toDataURL("image/png")后端文字转图片:text-to-svgsvg2pnghttps://www.cnblogs.com/duasonir/p/16700591......
  • 网页版红警的资源加载的实现
    由于红警的资源比较大,红警2加上红警尤里复仇两个版本,还有二十多首高清无损的背景音乐,有一个G左右的大小,当用户打开网页玩耍的时候,总不能每次都下载一个G的资源吧。所以需要......
  • 谷歌邮箱无法显示使用 Base64 处理的图片的解决方法
    前言有时候图片会使用Base64编码来处理,然后再传到前端img标签的src属性里展示,这里记录遇到的一个问题,就是使用谷歌邮箱来打开图片,使用了Base64编码处理的图片是展......
  • IDEA加载大文件时报错:The file size exceeds configured limit
    1,问题描述1Thefilesizeexceedsconfiguredlimit2,解决方案:配置一下idea.properties文件3,添加如下配置1idea.max.intellisense.filesize=500004,重启idea,完......
  • SAP UI5 应用如何加载自定义 Theme
    要加载外部自定义主题,开发人员可以通过在页面中静态声明或使用Core.setThemeRoot()方法来设置此主题。这非常类似于对位于不同位置的SAPUI5库使用registerModulePat......
  • 用html2canvas.js 将前端HTML页面生成图片
    首先去html2canvas官网下载html2canvas.js文件html2canvas官网地址:http://html2canvas.hertzen.com/HTML<divid="host_file"class="container"><divid="view"c......
  • SAP UI5 应用的标准 Theme 和自定义 Theme 的加载讨论
    SAPUI5应用的初始主题可以硬编码在应用程序中(在加载SAPUI5的引导程序的脚本标签中)或在加载SAPUI5之前定义的JS配置对象中,例如下面的例子:<scriptid="sap-ui-boots......