記錄一次js圖片壓縮思路

利用canvas進行圖片壓縮

思路: 建立一個canvas,將圖片繪製在畫布上,
經過設置canvas的寬度和質量,去調整圖片大小css

將file轉化爲base64

這一步是爲了建立一個image,在image中獲取寬高比html

// 將file轉化爲base64
  function changeFileToBaseURL(file, fn) {
    var flieReader = new FileReader()
    if(file == undefined) return fn(null)
    flieReader.readAsDataURL(file);
    flieReader.onload = function() {
      var imgBase64Data = this.result;
      fn(imgBase64Data)
    }
  }

將base64轉換爲file

在canvas完成圖片壓縮以後,以base64格式導出
這個時候能夠將base64轉換爲file方便回調函數操做canvas

// 將base64轉換爲file
  function dataURLToFile(dataUrl, fileName) {
    var arr = dataUrl.split(','), 
        mine = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while(n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], fileName, {type: mine})
  }

壓縮圖片的方法

/**
  * canvas壓縮圖片
  * @param {參數obj} param 
  * @param {文件二進制流} param.file 必傳
  * @param {目標壓縮大小} param.targetSize 不傳初始賦值-1
  * @param {輸出圖片寬度} param.width 不傳初始賦值-1,等比縮放不用傳高度
  * @param {輸出圖片名稱} param.fileName 不傳初始賦值image
  * @param {壓縮圖片程度} param.quality 不傳初始賦值0.92。值範圍0~1
  * @param {回調函數} param.succ(file, base64) 必傳
  */
  function imgCompress(param) {
    if(!(param && param.succ)) return
    if(param.file == undefined) return
    // param.targetSize = param.hasOwnProperty("targetSize") ? param.targetSize : -1
    param.width = param.hasOwnProperty("width") ? param.width : -1
    param.fileName = param.hasOwnProperty("fileName") ? param.fileName : 'image'
    param.quality = param.hasOwnProperty("quality") ? param.quality : 0.92
    var fileType = param.file.type
    if(fileType.indexOf('image') == -1) {
      console.log("請選擇圖片文件")
    }
    changeFileToBaseURL(param.file, function(base64) {
      if(base64) {
        var image = new Image();
        image.src = base64
        image.onload = function() {
          // 圖片的原始寬高比
          var scale = this.width / this.height
          var canvas = document.createElement('canvas')
          var context = canvas.getContext('2d')
          canvas.width = param.width == -1 ? this.width : param.width
          canvas.height = param.width == -1 ? this.height : parseInt(param.width / scale)
          context.drawImage(image, 0, 0, canvas.width, canvas.height)
          // 將canvas轉換爲base64和file格式,做爲回調參數
          var newImageData = canvas.toDataURL(fileType, param.quality);
          var resultFile = dataURLToFile(newImageData, param.fileName);
          param.succ(resultFile, newImageData)
        }
      }
    })
  }

結語

這裏雖然有targetSize的參數,可是這個參數並無使用上,
緣由是若是想要精確地將圖片大小轉換在某個數如下的話,須要用到遞歸去處理寬度,
這會對性能形成必定負擔。我沒有想到更好的方法...
能夠經過調整width和quality參數去知足接口大小限制。函數

調用

<div class="preview-box">
    <img src="" alt="">
    <p class="size"></p>
  </div>
  <input type="file" id="uploadBtn">
.preview-box{
    width: 300px;
    min-height: 300px;
  }
  img{
    width: 300px;
  }
var ipt = document.querySelector('#uploadBtn')
  var previewEl = document.querySelector('.preview-box img')
  var sizeEl = document.querySelector('.size')
  ipt.onchange = function() {
    imgCompress({
      file: this.files[0],
      targetSize: 1024 * 1024 * 1,
      width: 900,
      // quality: 1, 
      fileName: 'imgCompress',
      succ: function(file, base64) {
        previewEl.setAttribute('src', base64)
        sizeEl.innerHTML = file.size / 1024 / 1024 + 'M'
        console.log(file)
      }
    })
  }
相關文章
相關標籤/搜索