优化图片

68 阅读4分钟

图片懒加载

为什么要图片懒加载

懒加载(按需加载)是一种对网页性能优化的方式。比如当访问一个页面的时候,优先显示可视区域的图片而不是一次性加载所有图片,当需要显示时,再发送图片请求,避免打开网页时加载过多资源。 懒加载就是页面需要显示图片的时候才进行加载,否则不加载。

当一个网站的加载图片过多时就需要懒加载的协助,页面图片多时,在首次载入时一次性加载会耗费时间长,使用懒加载可以使页面加载速度快、减轻服务器的压力、节省流量。

图片渲染的特殊性

  1. 发送http请求先得到记录图片位置的字符串(src)
  2. image的src来发起请求,获取对应的图片放置到DOM树的这个位置上,从而实现图片的页面渲染。

图片懒加载的实现原理:图片的src按需发起请求,获取图片。

  • 使用 html5 提供的自定义属性:data-xxx 存储图片地址。
  • 使用 src 进行占位:每个照片都是相同的 src,当页面有多张重复图片时,只会发起一次请求。
  • 判断图片是否在屏幕上:元素到屏幕顶部的距离小于屏幕高度时,就可以判定图片进入了屏幕。就把图片地址赋值给src,从而发起请求获取图片。 DOMobj.getBoundingClientRect().top //获取该元素到屏幕顶部的距离 window.innerHeight //屏幕的高度

图片懒加载的实现

<img data-src="./151654845377_.pic.jpg" height="800px" > <br>
<img data-src="./161654845508_.pic_hd.jpg" height="800px" > <br>
<img data-src="./1.jpeg"  height="800px"> <br>
<img data-src="./2.jpeg"  height="800px">

原生js实现

const isInView = (el) => {
    const { top, left, height, width } = el.getBoundingClientRect();
    const clientHeight =
      window.innerHeight || document.documentElement.clientHeight;
    const clientWidth = window.innerWidth;
    document.documentElement.clientWidth;
    if (top < clientHeight && left < clientWidth) {
    return true;
    }
    return false;
  };

  const lazyload = () => {
    const imgList = [...document.getElementsByTagName('img')];
    if (!imgList.length) {
      document.removeEventListener("scroll", lazyload);
      return;
    }
    imgList.forEach((img) => {
      if (!img.src && isInView(img)) {
        img.src = img.dataset.src;;
      }
    });
  };

  // 第一次加载 屏幕内的图片正常显示,屏幕外的使用loading图片代替
  window.onload = lazyload;
  // 监听事件
  document.addEventListener("scroll", lazyload, {passive: true});

使用IntersectionObserver API 

document.addEventListener('DOMContentLoaded', function() {
    let imgList = [...document.getElementsByTagName('img')];
    if("IntersectionObserver" in window) {
      let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
        entries.forEach((item) => {
          if (item.isIntersecting) {
            item.target.src = item.target.dataset.src;
            lazyImageObserver.unobserve(item.target);
          }
        });
      });
      // 对所有需要懒加载的图片进行 “暗中观察”
      imgList.forEach(function(lazyImage) {
		    lazyImageObserver.observe(lazyImage);
		  });
    } else {
      console.log('您的浏览器不支持 IntersectionObserver');
    }
  })

响应式图片

网页在不同尺寸的设备上,都有良好的显示效果,叫做"响应式设计"(responsive web design)。

响应式设计的网页图像,就是"响应式图像"(responsive image)。

像素密度选择:srcset属性

<img />标签引入 srcset 属性来实现响应式图片。

srcset属性用来指定多张图像,适应不同像素密度的屏幕。它的值是一个逗号分隔的字符串,每个部分都是一张图像的 URL,后面接一个空格,然后是像素密度的描述符。

<img srcset="foo-320w.jpg,
             foo-480w.jpg 1.5x,
             foo-640w.jpg 2x"
     src="foo-640w.jpg">

像素描述的格式:像素密度倍数 + 字母x。 1x:单倍像素密度,可以省略。

浏览器根据当前设备的像素密度,选择需要加载的图像。如果srcset属性都不满足条件,那么就加载src属性指定的默认图像。

图像大小的选择:srcset属性 + sizes属性

像素密度的适配,只适合显示区域一样大小的图像。如果希望不同尺寸的屏幕,显示不同大小的图像,srcset属性就不够用了,必须搭配sizes属性。

<img srcset="foo-160.jpg 160w,
             foo-320.jpg 320w,
             foo-640.jpg 640w,
             foo-1280.jpg 1280w"
     sizes="(max-width: 440px) 100vw,
            (max-width: 900px) 33vw,
            254px"
     src="foo-1280.jpg">
  1. srcset属性列出所有可用的图像。
    宽度描述符就是图像原始的宽度,加上字符w
    上例的四种图片的原始宽度分别为160像素、320像素、640像素和1280像素。
  2. sizes属性列出不同设备的图像显示宽度。
    sizes属性给出了三种屏幕条件,以及对应的图像显示宽度。宽度不超过440像素的设备,图像显示宽度为100%;宽度441像素到900像素的设备,图像显示宽度为33%;宽度900像素以上的设备,图像显示宽度为 254px。
  3. 浏览器根据当前设备的宽度,从sizes属性获得图像的显示宽度,然后从srcset属性找出最接近该宽度的图像,进行加载。

WebP图片格式优化

WebP 是由谷歌(Google)推出的一种旨在加快图片加载速度的图片格式,在相同质量的情况下,WebP 的体积要比 JPEG 格式小 25% ~ 34%。

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp">
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>

始终在图像和视频元素上包括width和设置height尺寸属性。以确保在浏览器开始获取图像之前在页面上分配了足够的空间。这将最大程度地减少回流和重新布局。

响应式图像教程 阮一峰