基本概念
图片的类型
平时比较常见的图片类型有:jpg
、jpeg
、png
、svg
、bmp
、gif
、webp
jpg
优点: jpg
是一种有损的基于直接色的图片格式。由于采用直接色,jpg
可使用的颜色有 1600w
之多,而人眼识别的颜色数量大约只有 1w
多种,因此 jpg
非常适合色彩丰富图片、渐变色。jpg
有损压缩移除肉眼无法识别的图片细节后,可以将图片的尺寸大幅度地减小
缺点: jpg
不适合 icon
、logo
,因为相比 gif
/ png-8
,它在文件大小上丝毫没有优势
应用场景: 色彩丰富的网络图片使用
PNG8
优点: png-8
采用无损压缩,是基于 8 位索引色的位图格式。png-8
相比 gif
对透明的支持更好,同等质量下,尺寸也更小。非常适合作为 gif
的替代品
缺点: png-8
也一个明显的不足就是不支持动画
应用场景: 主要用于小图标或颜色简单对比强烈的小的背景图
PNG24
优点: png-24
采用无损压缩,是基于直接色的位图格式。png-24
的图片质量堪比 bmp
,但是却有 bmp
不具备的尺寸优势。当然相比于 jpg
,gif
,png-8
,尺寸上还是要大。正是因为其高品质,无损压缩,非常适合用于源文件或需要二次编辑的图片格式的保存。支持透明
缺点: 图片存储为 png-24
比存储为 jpg
,文件大小至少是 jpg
的 5 倍,但在图片品质上的提升却微乎其微。所以除非对品质的要求极高,否则色彩丰富的网络图片还是推荐使用 jpg
应用场景: 对品质的要求极高的图片
GIF
优点: 采用 LZW
压缩算法进行编码,是一种无损的基于索引色的图片格式。由于采用了无损压缩,相比古老的 bmp
格式,尺寸较小,而且支持透明和动画
缺点: gif
只存储8位索引(也就是最多能表达 2^8=256
种颜色),色彩复杂、细节丰富的图片不适合保存为 gif
格式。色彩简单的 logo
、icon
、线框图适合采用 gif
格式
应用场景: 主要用于比较小的动态图标
SVG
优点: SVG
是矢量图形,不受像素影响,在不同平台上都表现良好;可以通过 JS
控制实现动画效果
缺点: 因为是矢量图,不能展现位图的丰富真实色彩
应用场景: 矢量图形,可缩放;无需多端、多分辨率适配;支持多种编辑,具有较强的交互特性
webp
优点: WebP
图片是一种新的图像格式,由 Google
开发。与 png
、jpg
相比,相同的视觉体验下,WebP
图像的尺寸缩小了大约 30%
。另外,WebP
图像格式还支持有损压缩、无损压缩、透明和动画。理论上完全可以替代png
、jpg
、gif
等图片格式
缺点: 目前 webp
的还没有得到全面的支持,存在兼容性问题
应用场景: 高压缩比,适合网络快速传输
矢量图与栅格图像
矢量图
使用线、点和多边形来表示图像,前端最常见的矢量图是 SVG
,SVG
适用于包含简单的几何图形的图像,因为 SVG
缩放不失真,所以 SVG
最适合用于高分辨率屏幕和需要以不同尺寸显示的图像
栅格图像
- 由一个个的像素栅格组成
- 每个像素都编码了颜色和透明度信息
- 使用不同的压缩算法(不同的图片格式),以减小图像的文件大小
图片格式分类
- 无压缩:无压缩的图片格式不对图片数据进行压缩处理,能准确地呈现原图片。
BMP
格式就是其中之一 - 无损压缩:压缩算法对图片的所有的数据进行编码压缩,能在保证图片的质量的同时降低图片的尺寸。
png
是其中的代表 - 有损压缩:压缩算法不会对图片所有的数据进行编码压缩,而是在压缩的时候,去除了人眼无法识别的图片细节。因此有损压缩可以在同等图片质量的情况下大幅降低图片的尺寸。其中的代表是
jpg
优化
一、延迟加载(懒加载)
首先我们不动图片本身,从图片外部来考虑,那就很容易想到延迟加载 — 也叫懒加载。顾名思义,就是图片过多的时候,把后续的图片延迟一会儿,等到需要的时候再进行加载显示。现在一张图片超过几兆已经是很经常的事了,如果每次进入页面就请求所有的图片资源,那么可能等图片加载出来用户也早就走了。所以,我们需要懒加载,进入页面的时候,只请求可视区域的图片资源
实现方式
延迟加载的方式大概可以总结成以下几点:
- 设置图片
src
属性为同一张图片(一般放置加载loading
图片,也就是所谓的菊花图),同时自定义一个data-src
属性来存储图片的真实地址 - 页面初始化显示的时候或者浏览器发生滚动的时候判断图片是否在视野中
- 当图片在视野中时,通过
js
自动改变该区域的图片的src
属性为data-src
中的真实地址
Vue 的实现
Vue
中实现图片的异步加载有更方便的方式,直接使用 vue-lazyload
库就可以轻松实现
Vue.use(VueLazyload, {
error: require('./assets/loading.svg'), // error 时候展示的图
loading: require('./assets/loading.svg'), // 加载中
attempt: 1 // viewport 视窗
})
一次加载两个视窗范围的图片,图片上 v-lazy
<template>
<div id="app">
<div v-for="(img, index) in images" :key="index">
<img v-lazy="img">
</div>
</div>
</template>
二、渐进式图片
尽管懒加载在性能方面表现出色,但是用户滚动屏幕后需要盯着空白区域等待图片加载,这样的用户体验不太好。网速慢的情况下,下载图片会非常慢。所以我们还需要渐进式图片
渐进式图片的意思是在高画质图像加载完之前会先显示低画质版本。低画质版本由于画质低、压缩率高,尺寸很小,加载很快。在两者之间我们也可以根据需要显示不同画质的版本
渐进式图片其实是一种 JPEG
格式的图片,和普通的 JPEG
图片的区别如下:
- 普通图片渲染时,数据将按照存储时的顺序从上到下逐行扫描被显示出来的,直到所有的数据都被读取完毕,就完成了整张图片的显示
- 渐进式图片渲染过程中,会先显示整个图片的模糊轮廓,随着扫描次数的增加,图片变得越来越清晰。这种格式的主要优点是在网络较慢的情况下,可以看到图片的轮廓知道正在加载的图片大概是什么
类似于先加载页面的骨架,渐进式图片这一技术让用户产生图片加载变快的印象。用户不再盯着一片空白区域等待事情发生,而能看到图像变得越来越清晰
三、图片预加载
如果我们的图片在页面中起着很重要的作用,想快点渲染出来,那可以使用 <link rel=preload>
预加载。 <link rel=preload>
是声明性提取,允许强制浏览器在不阻止文档的 onload
事件的情况下请求资源。 其可提高资源请求的优先级,否则这些资源可能会在之后的文档解析过程中才会出现。 <img>
、<picture>
、srcset
和 SVG
的图像资源都可以利用此优化策略
四、使用Webp
同样尺寸的图片,WebP
有损文件比 JPEG
文件小 25%
至 34%
,WebP
无损文件比 PNG
文件小 26%
,但是WebP 的全球用户支持率大约为 74%
我们可以通过 node
使用 webp-converter
的 npm
包来实现把图片压缩成 webp
格式
// 转换 webp 格式示例(在图片比较大的情况下)
const webp = require('webp-converter')
webp.cwebp('test.jpg', 'test.webp', '-q 80',
function(status, error) {
console.log(status, error)
}
)
兼容 webp
- 使用
<picture>
标记
<picture>
<source srcset="bg1.webp" type="image/webp">
<source srcset="bg2.jpg" type="image/jpeg">
<img src="bg.jpg" alt="背景图">
</picture>
<picture>
标记使用多个 <source>
元素,并且包括一个 <img>
标记,而该标记是真正的 DOM
元素,包含图像。 浏览器循环切换源代码并检索第一个匹配项。 如果用户的浏览器不支持 <picture>
标记,则会呈现 <div>
并使用 <img>
标记
- 使用
canvas
判断
export const isSupportWebp = () => {
try {
return (
document
.createElement("canvas")
.toDataURL("image/webp")
.indexOf("data:image/webp") == 0
);
} catch (err) {
return false;
}
};
判断是否支持 webp
后拼装对应 url
向服务器获取相关图片资源
五、雪碧图 CSS Sprites
对于一些小图片,比如图标等,可以采用雪碧图的方案,将多张比较小的图片,合并到一张大的图片上面,大的图片背景透明,使用的时候,通过把该张图片当做背景图片,通过不同的 background-position
定位来展示的那部分图片
优点
- 降低服务器压力
- 减少网络请求,页面渲染更快
缺点
- 后期维护困难,添加一张图片需要重新制作
- 应用麻烦,每一张图都需要计算位置,通过调整位置来展示图片,对误差的要求很严格
- 使用图片有局限,只能用在背景图片
background-image
上,不能用<img>
标签来使用
六、iconfont
对于图标等,也可以采用字体图标 iconfont
代替图片,图标可以像字体一样修改大小、颜色等样式
优点
- 可以方便地将任何
CSS
效果应用于它们 - 因为它们是矢量图形,所以它们是可伸缩的。这意味着我们可以在不降低质量的情况下伸缩它们
- 我们只需要发送一个或少量
HTTP
请求来加载它们,而不是像图片,可能需要多个HTTP
请求 - 由于尺寸小,它们加载速度快
- 它们在所有浏览器中都得到支持(甚至支持到
IE6
)
缺点
- 不能用来显示复杂图像
- 通常只限于一种颜色,除非应用一些
CSS
技巧 - 字体图标通常是根据特定的网格设计的,例如
16x16
,32×32
,48×48
等。如果由于某种原因将网格系统改为25×25
,可能不会得到清晰的结果
阿里 IconFont
:
https://www.iconfont.cn/?spm=a2c6h.12873639.0.0.63633cbbvwdc2G