前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Web技术】907- 前端图片最优化压缩方案

【Web技术】907- 前端图片最优化压缩方案

作者头像
pingan8787
发布2021-04-07 15:08:37
8660
发布2021-04-07 15:08:37
举报
文章被收录于专栏:前端自习课前端自习课

前言

上传图片/视频/文件是我们经常会遇到的问题,但是一旦图片过大就会导致不好的操作体验。图片上传是前端中常见的的业务场景。无论是前台还是后台,适当的对图片进行压缩处理, 可以显著的提升用户体验。而在后台管理系统中,图片压缩不仅仅能够提升后台管理员操作体验,更是可以防止后台设置过大的图片导致前台图片加载过久,从而影响用户体验。

关于压缩图片

思考

想想压缩图片基本流程

  • input 读取到 文件 ,使用 FileReader 将其转换为 base64 编码
  • 新建 img ,使其 src 指向刚刚的 base64
  • 新建 canvas ,将 img 画到 canvas 上
  • 利用 canvas.toDataURL/toBlob 将 canvas 导出为 base64 或 Blob
  • 将 base64 或 Blob 转化为 File

将这些步骤逐个拆解,我们会发现似乎在canvas.toDataURL时涉及到图片质量,那咱们就从这里下手。

准备

HTMLCanvasElement.toDataURL()

HTMLCanvasElement.toDataURL() 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。

  • 如果画布的高度或宽度是0,那么会返回字符串“data:,”。
  • 如果传入的类型非“image/png”,但是返回的值以“data:image/png”开头,那么该传入的类型是不支持的。

语法

canvas.toDataURL(type, encoderOptions);

参数

  • type 可选

图片格式,默认为 image/png

  • encoderOptions 可选

在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。Chrome支持“image/webp”类型。

猜想

可能toDataURL(type,quality)的第二个参数(quality)越小,文件体积越小

实践

先看下原图信息大小是7.31kb

toDataURL(type,quality)quality默认0.92看看压缩结果如何

代码语言:javascript
复制
<input id="fileInput" type="file" />
<img id="img" src="" alt="">
复制代码
代码语言:javascript
复制
let fileId = document.getElementById('fileInput')
let img = document.getElementById('img')
fileId.onchange = function (e) {
  let file = e.target.files[0]
  compressImg(file, 0.92).then(res => {//compressImg方法见附录
    console.log(res)
    img.src = window.URL.createObjectURL(res.file);
  })
}
复制代码

compressImg方法见附录

可以看到图片大小为8.83kb压缩后图片反而变大了,这是怎么回事?

看来起初的猜想不完全正确,咱们继续看看。

代码语言:javascript
复制
fileId.onchange = function (e) {
  let file = e.target.files[0]
  compressImg(file, 0.1).then(res => {//compressImg方法见附录
    console.log(res)
    img.src = window.URL.createObjectURL(res.file);
  })
}
复制代码

quality为0.1的时候,图片仅有1.63kb,同样的质量也下降了

继续......A long time later

咱们用折线图来看吧更直观

我又拿了几个图片让他们使用默认值0.92,结果都比原图大

所以说默认值得到的图片往往比原图大

下面看看当quality为多少时对图片的压缩效率可以最大化

压缩效率最大化,即:在不影响图片质量的情况下最大化压缩

尝试了一系列的图片之后我发现 当quality在0.2~0.5之间,图片质量变化并不大,quality的值越小,压缩效率越可观(也就是在0.2左右时,压缩图片可以最大化,同时并不对图片质量造成太大影响)

结论

经过实践,可以得出结论这个默认值得到的图片往往比原图的图片质量要高。

quality在0.2~0.5之间,图片质量变化并不大,quality的值越小,压缩效率越可观(也就是在0.2左右时,压缩图片可以最大化,同时并不对图片质量造成太大影响)

附录

代码语言:javascript
复制
/**
 * 压缩方法 
 * @param {string} file 文件
 * @param {Number} quality  0~1之间
*/
function compressImg(file, quality) {
  if (file[0]) {
    return Promise.all(Array.from(file).map(e => compressImg(e,
      quality))) // 如果是 file 数组返回 Promise 数组
  } else {
    return new Promise((resolve) => {
      const reader = new FileReader() // 创建 FileReader
      reader.onload = ({
        target: {
          result: src
        }
      }) => {
        const image = new Image() // 创建 img 元素
        image.onload = async () => {
          const canvas = document.createElement('canvas') // 创建 canvas 元素
          canvas.width = image.width
          canvas.height = image.height
          canvas.getContext('2d').drawImage(image, 0, 0, image.width, image.height) // 绘制 canvas
          const canvasURL = canvas.toDataURL('image/jpeg', quality)
          const buffer = atob(canvasURL.split(',')[1])
          let length = buffer.length
          const bufferArray = new Uint8Array(new ArrayBuffer(length))
          while (length--) {
            bufferArray[length] = buffer.charCodeAt(length)
          }
          const miniFile = new File([bufferArray], file.name, {
            type: 'image/jpeg'
          })
          resolve({
            file: miniFile,
            origin: file,
            beforeSrc: src,
            afterSrc: canvasURL,
            beforeKB: Number((file.size / 1024).toFixed(2)),
            afterKB: Number((miniFile.size / 1024).toFixed(2))
          })
        }
        image.src = src
      }
      reader.readAsDataURL(file)
    })
  }
}
复制代码
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端自习课 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于压缩图片
    • 思考
      • 准备
        • HTMLCanvasElement.toDataURL()
        • 语法
        • 参数
      • 猜想
        • 实践
          • 结论
          • 附录
          相关产品与服务
          文件存储
          文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档