图片优化

图片优化

为什么要做图片优化?

Google官方的最佳实践中关于图片优化有下面这样一段描述:

对于网页来说,在所下载的字节数中,图片往往会占很大比例。因此,优化图片通常可以卓有成效地减少字节数和改进性能:浏览器需要下载的字节数越少,对客户端带宽的争用就越少,浏览器下载内容并在屏幕上呈现内容的速度就越快。

我们可以通过一些第三方方法来看一下在一个网站中,图片所占比例的大小:使用webTest网站,可以清楚的看到一个网站首屏加载时,图片所占比例的大小。而且电商网站中,图片所占比例占比是最大的。

通过优化图片可以减少客户端下载的字节数,改进网页性能。

图片类型和使用场景

一般常用的图片格式有那么几种:JPEG/JPG、PNG、WebP、Base64、SVG。

JPEG和JPG格式有什么区别?

没有区别,全名、正式扩展名是JPEG。但因DOS、Windows 95等早期系统采用的8.3命名规则只支持最长3字符的扩展名,为了兼容采用了.jpg。也因历史习惯和兼容性考虑,.jpg目前更流行。

JPEG/JPG

特点:有损压缩,体积小,加载快,不支持透明。

适用场景:适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现。

PNG

特点:无损压缩,体积大,质量高,支持透明。

适用场景:PNG 在处理线条和颜色对比度方面有优势,主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等

SVG

特点:文本文件,体积线,不失真,兼容性好。

适用场景:将 SVG 写入独立文件后引入 HTML

<img src="文件名.svg" alt="">

Base64

特点:文本文件、依赖编码、小图标解决方案。

适用场景:小图标,更新频率非常低,作为雪碧图的补充。

WebP

WebP 是 Google 专为 Web 开发的一种旨在加快图片加载速度的图片格式,它支持有损压缩和无损压缩。

特点:全能,但是有兼容性问题。

适用场景:限制我们使用 WebP 的最大问题不是“这个图片是否适合用 WebP 呈现”,而是“浏览器是否允许 WebP”。

图片优化方案

减少图片体积

使用WebP的方式,都可以在不降低图片质量的条件下,减少图片体积的。

WebP 的优势是它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。

cloudconvert可以在线转换WebP图片。

在淘宝首页,就有一些图片就是WebP类型的。淘宝是根据浏览器是否支持WebP来动态的设置图片url的。

那么如何判断浏览器是否支持WebP呢?

Google官方文档是这样处理的(先加载一个WebP图片,如果能获取到图片的宽度和高度,就说明是支持WebP的,反之则不支持):

function check_webp_feature(feature, callback) {
    var kTestImages = {
        lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
        lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
        alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
        animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
    };
    var img = new Image();
    img.onload = function () {
        var result = (img.width > 0) && (img.height > 0);
        callback(feature, result);
    };
    img.onerror = function () {
        callback(feature, false);
    };
    img.src = "data:image/webp;base64," + kTestImages[feature];
}

原理:对每一种格式的webp(有损,无损,alpha通道,动态)生成一个很小像素的图片,在浏览器中渲染,如果没有问题,就代表支持webp。

还有一种方法,就是让服务器来判断浏览器是否支持WebP格式:服务器通过HTTP请求头的Accept字段,来判断返回什么格式的图片。当 Accept 字段包含 image/webp 时,就返回 WebP 格式的图片,否则返回原图。

利用SVGO压缩svg文件的大小。

缓存

图片懒加载

懒加载的原理是:将图片的url赋值给img的data-url(可自定义)属性,监听滚动事件,当图片进入可视区域时,将data-url的值赋值给img的url属性,这时才真正发出图片的http请求。

// 简单的节流函数
//fun 要执行的函数
//delay 延迟
//time  在time时间内必须执行一次
function throttle(fun, delay, time) {
    var timeout,
        startTime = new Date();

    return function() {
        var context = this,
            args = arguments,
            curTime = new Date();

        clearTimeout(timeout);
        // 如果达到了规定的触发时间间隔,触发 handler
        if (curTime - startTime >= time) {
            fun.apply(context, args);
            startTime = curTime;
            // 没达到触发间隔,重新设定定时器
        } else {
            timeout = setTimeout(fun, delay);
        }
    };
};
// 实际想绑定在 scroll 事件上的 handler
function lazyload(event) {
    for (var i = n; i < imgNum; i++) {
        if (img.eq(i).offset().top < parseInt($(window).height()) + parseInt($(window).scrollTop())) {
            if (img.eq(i).attr("src") == "default.jpg") {
                var src = img.eq(i).attr("data-src");
                img.eq(i).attr("src", src);

                n = i + 1;
            }
        }
    }
}
// 采用了节流函数
window.addEventListener('scroll', throttle(lazyload, 500, 1000));

响应式图片

一种可以在不同的屏幕尺寸和分辨率的设备上都能良好工作以及其他特性的图片.

艺术方向

当你想为不同布局提供不同剪裁的图片——比如在桌面布局上显示完整的、横向图片,而在手机布局上显示一张剪裁过的、突出重点的纵向图片,可以用 元素来实现。

<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>

分辨率切换

当你想要为窄屏提供更小的图片时,因为小屏幕不需要像桌面端显示那么大的图片;以及你想为高/低分辨率屏幕提供不同分辨率的图片时,都可以通过 vector graphics (SVG images)、 srcset 以及 sizes 属性来实现。

分辨率切换:不同的尺寸

<img srcset="elva-fairy-320w.jpg 320w,
             elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

分辨率切换: 相同的尺寸, 不同的分辨率

<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">

一般情况下当我们给img设置固定的宽的时候,为了在不同的dpr设备上显示相同的大小,可以配合x来,例如1.5x代表dpr为1.5的设备

srcset/sizes/ 新特性

已经被新版本的现代浏览器和移动浏览器所支 持(包括Edge,而不是IE)。

  • srcset语法: “图片路径 物理像素, 图片路径 物理像素, …..”。
  • size: “媒体查询 css像素”。
  • src: 当浏览器不支持上面的属性的时候,默认加载这里。

加载的流程如下:

  • 查看设备宽度
  • 查看sizes中哪一个媒体查询条件为真。
  • 查看给予该媒体查询的槽大小。
  • 加载srcset列表中引用的最接近所选的槽大小的图像

一般 1px = 1w

其他方案

雪碧图

base64编码内联小图片

cdn加速

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!