1. 程式人生 > >基於canvas實現圖片壓縮

基於canvas實現圖片壓縮

用法:
compressImg(target.files[0], 2).then(base64 => {
  console.log(base64)
  // 在這裡實現壓縮後的上傳操作
  // ...
}).catch(err => { // 壓縮異常
  Indicator.close()
  _this.$toast(err)
})

詳細見程式碼註釋


/**
 * 圖片壓縮
 * @param file 圖片原檔案【必傳】
 * @param maxDefaultSize 壓縮後的最大值限制,預設10M
 * @param quality 壓縮後的質量,取值範圍:(0, 1], 預設值:1
 * @param type 壓縮後的檔案字尾名, 預設值:'jpeg'
 * @returns {Promise<any>}
 */
export function compressImg (file = null, maxDefaultSize = 10, quality = 1, type = 'jpeg') {
  let imgQuality = quality > 1 ? 1 : quality <= 0 ? 0.1 : quality // imgQuality取值範圍:(0, 1]
  let reader = new FileReader()
  let img = new Image()
  // 圖片轉base64後的大小
  let imgSize = 0
  // 選擇的檔案是圖片
  if (file.type.indexOf('image') === 0) {
    reader.readAsDataURL(file)
  }
  // 檔案base64化,以便獲知圖片原始尺寸
  reader.onload = function (e) {
    imgSize = e.total
    img.src = e.target.result
  }
  // 建立縮放圖片所需的canvas
  let canvas = document.createElement('canvas')
  let context = canvas.getContext('2d')
  // 返回promise物件
  return new Promise((resolve, reject) => {
    // base64地址圖片載入完畢後
    img.onload = (e) => {
      // 圖片原始尺寸
      let originWidth = img.width
      let originHeight = img.height
      // 最大尺寸限制和最大圖片佔用空間限制
      let maxWidth = 500
      let maxHeight = 500
      let maxSize = 2 * 1024 * 1024 // 2M
      // 目標尺寸
      let targetWidth = originWidth
      let targetHeight = originHeight
      // 圖片尺寸超過500*500最大尺寸的限制,或超過2M限制
      if (imgSize > maxSize || originWidth > maxWidth || originHeight > maxHeight) {
        // 圖片原始寬高比例大於最大寬高比例,按照寬度限定尺寸
        if (originWidth / originHeight > maxWidth / maxHeight) {
          targetWidth = maxWidth
          targetHeight = Math.round(maxWidth * (originHeight / originWidth))
        } else {
          targetWidth = Math.round(maxHeight * (originWidth / originHeight))
          targetHeight = maxHeight
        }
      }

      // 使用canvas對圖片進行縮放壓縮操作
      canvas.width = targetWidth
      canvas.height = targetHeight
      // 清除畫布
      context.clearRect(0, 0, targetWidth, targetHeight)
      // 圖片壓縮
      context.drawImage(img, 0, 0, targetWidth, targetHeight)
      // canvas轉為base64上傳
      let targetType = type ? `image/${type}` : file.type || 'image/jpeg'
      let base64 = canvas.toDataURL(targetType, imgQuality)
      let strContent = base64.split('base64,')[1].replace(/=/g, '')
      let contentLen = strContent.length
      let base64Size = parseInt(contentLen - (contentLen / 8) * 2)
      // 壓縮後還大於壓縮後最大值限制
      if (base64Size > maxDefaultSize * 1024 * 1024) {
        let errMsg = '圖片過大,請重新選擇'
        reject(errMsg)
      } else {
        resolve(base64)
      }
      // canvas轉為blob上傳
      // canvas.toBlob((blob) => {
      //   console.log('canvas轉為blob上傳---', blob)
      //   resolve(blob)
      // }, `image/${type}` || file.type || 'image/jpeg')
    }
    img.onerror = () => {
      let errMsg = '圖片載入失敗'
      reject(errMsg)
    }
  })
}