最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端图片最优化压缩方案

    正文概述 掘金(凉城a)   2021-03-17   1229

    前言

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

    关于压缩图片

    思考

    想想压缩图片基本流程

    • 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”开头,那么该传入的类型是不支持的。

    语法

    参数

    • 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看看压缩结果如何

    <input id="fileInput" type="file" />
    <img id="img" src="" >
    
    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压缩后图片反而变大了,这是怎么回事?

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

    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左右时,压缩图片可以最大化,同时并不对图片质量造成太大影响)

    附录

    /**
     * 压缩方法 
     * @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)
        })
      }
    }
    

    起源地下载网 » 前端图片最优化压缩方案

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元