<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端圖片最優(yōu)化壓縮方案

          共 3858字,需瀏覽 8分鐘

           ·

          2021-03-26 10:25

          作者:涼城a

          原文:https://juejin.cn/post/6940430496128040967

          前言

          上傳圖片/視頻/文件是我們經(jīng)常會(huì)遇到的問題,但是一旦圖片過大就會(huì)導(dǎo)致不好的操作體驗(yàn)。圖片上傳是前端中常見的的業(yè)務(wù)場(chǎng)景。無(wú)論是前臺(tái)還是后臺(tái),適當(dāng)?shù)膶?duì)圖片進(jìn)行壓縮處理, 可以顯著的提升用戶體驗(yàn)。而在后臺(tái)管理系統(tǒng)中,圖片壓縮不僅僅能夠提升后臺(tái)管理員操作體驗(yàn),更是可以防止后臺(tái)設(shè)置過大的圖片導(dǎo)致前臺(tái)圖片加載過久,從而影響用戶體驗(yàn)。

          關(guān)于壓縮圖片

          思考

          想想壓縮圖片基本流程

          • input 讀取到 文件 ,使用 FileReader 將其轉(zhuǎn)換為 base64 編碼

          • 新建 img ,使其 src 指向剛剛的 base64

          • 新建 canvas ,將 img 畫到 canvas 上

          • 利用 canvas.toDataURL/toBlob 將 canvas 導(dǎo)出為 base64 或 Blob

          • 將 base64 或 Blob 轉(zhuǎn)化為 File

          將這些步驟逐個(gè)拆解,我們會(huì)發(fā)現(xiàn)似乎在canvas.toDataURL時(shí)涉及到圖片質(zhì)量,那咱們就從這里下手。

          準(zhǔn)備

          HTMLCanvasElement.toDataURL()

          HTMLCanvasElement.toDataURL() 方法返回一個(gè)包含圖片展示的 data URI 。可以使用 type 參數(shù)其類型,默認(rèn)為 PNG 格式。圖片的分辨率為96dpi。

          • 如果畫布的高度或?qū)挾仁?,那么會(huì)返回字符串“data:,”。

          • 如果傳入的類型非“image/png”,但是返回的值以“data:image/png”開頭,那么該傳入的類型是不支持的。

          語(yǔ)法

          canvas.toDataURL(type, encoderOptions);

          參數(shù)

          • type 可選

          圖片格式,默認(rèn)為 image/png

          • encoderOptions 可選

          在指定圖片格式為 image/jpeg 或 image/webp的情況下,可以從 0 到 1 的區(qū)間內(nèi)選擇圖片的質(zhì)量。如果超出取值范圍,將會(huì)使用默認(rèn)值 0.92。其他參數(shù)會(huì)被忽略。Chrome支持“image/webp”類型。

          猜想

          可能toDataURL(type,quality)的第二個(gè)參數(shù)(quality)越小,文件體積越小

          實(shí)踐

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

          toDataURL(type,quality)quality默認(rèn)0.92看看壓縮結(jié)果如何

          <input id="fileInput" type="file" />
          <img id="img" src="" alt="">
          復(fù)制代碼
          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);
          })
          }
          復(fù)制代碼

          compressImg方法見附錄

           可以看到圖片大小為8.83kb壓縮后圖片反而變大了,這是怎么回事?

          看來(lái)起初的猜想不完全正確,咱們繼續(xù)看看。

          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);
          })
          }
          復(fù)制代碼

           當(dāng)quality為0.1的時(shí)候,圖片僅有1.63kb,同樣的質(zhì)量也下降了

          繼續(xù)......A long time later

          咱們用折線圖來(lái)看吧更直觀

           我又拿了幾個(gè)圖片讓他們使用默認(rèn)值0.92,結(jié)果都比原圖大

          所以說(shuō)默認(rèn)值得到的圖片往往比原圖大

          下面看看當(dāng)quality為多少時(shí)對(duì)圖片的壓縮效率可以最大化

          壓縮效率最大化,即:在不影響圖片質(zhì)量的情況下最大化壓縮

          嘗試了一系列的圖片之后我發(fā)現(xiàn) 當(dāng)quality在0.2~0.5之間,圖片質(zhì)量變化并不大,quality的值越小,壓縮效率越可觀(也就是在0.2左右時(shí),壓縮圖片可以最大化,同時(shí)并不對(duì)圖片質(zhì)量造成太大影響)

          結(jié)論

          經(jīng)過實(shí)踐,可以得出結(jié)論這個(gè)默認(rèn)值得到的圖片往往比原圖的圖片質(zhì)量要高。

          當(dāng)quality在0.2~0.5之間,圖片質(zhì)量變化并不大,quality的值越小,壓縮效率越可觀(也就是在0.2左右時(shí),壓縮圖片可以最大化,同時(shí)并不對(duì)圖片質(zhì)量造成太大影響)

          附錄

          /**
          * 壓縮方法
          * @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 數(shù)組返回 Promise 數(shù)組
          } else {
          return new Promise((resolve) => {
          const reader = new FileReader() // 創(chuàng)建 FileReader
          reader.onload = ({
          target: {
          result: src
          }
          }) => {
          const image = new Image() // 創(chuàng)建 img 元素
          image.onload = async () => {
          const canvas = document.createElement('canvas') // 創(chuàng)建 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)
          })
          }
          }
          復(fù)制代碼
          ??愛心三連擊

          1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的點(diǎn)贊在看是我創(chuàng)作的動(dòng)力。

          2.關(guān)注公眾號(hào)程序員成長(zhǎng)指北,回復(fù)「1」加入高級(jí)前端交流群!「在這里有好多 前端 開發(fā)者,會(huì)討論 前端 Node 知識(shí),互相學(xué)習(xí)」!

          3.也可添加微信【ikoala520】,一起成長(zhǎng)。

          “在看轉(zhuǎn)發(fā)”是最大的支持

          瀏覽 103
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷五月大片 | 天堂中文在线资源库5 | 影音先锋男人网 | 日韩视频在线观看免费 | 国产成人免费 |