image.js 2.5 KB
Newer Older
fv2010's avatar
fv2010 已提交
1
export default class ImageCompress {
何秀钢 已提交
2 3 4 5 6
  constructor(file, fileSize, maxWH = 1920) {
    this.file = file
    this.fileSize = fileSize
    this.maxWH = maxWH // 最大长宽
  }
fv2010's avatar
fv2010 已提交
7

何秀钢 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  compress() {
    // 压缩
    const fileType = this.file.type
    const fileSize = this.file.size / 1024
    return new Promise(resolve => {
      const reader = new FileReader()
      reader.readAsDataURL(this.file)
      reader.onload = () => {
        const canvas = document.createElement('canvas')
        const img = document.createElement('img')
        img.src = reader.result
        img.onload = () => {
          const ctx = canvas.getContext('2d')
          const _dWH = this.dWH(img.width, img.height, this.maxWH)
          canvas.width = _dWH.width
          canvas.height = _dWH.height
fv2010's avatar
fv2010 已提交
24

何秀钢 已提交
25 26 27
          // 清空后, 重写画布
          ctx.clearRect(0, 0, canvas.width, canvas.height)
          ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
fv2010's avatar
fv2010 已提交
28

何秀钢 已提交
29
          const newImgData = canvas.toDataURL(fileType, 0.90)
fv2010's avatar
fv2010 已提交
30

何秀钢 已提交
31 32
          // 压缩宽高后的图像大小
          const newImgSize = this.fileSizeKB(newImgData)
fv2010's avatar
fv2010 已提交
33

何秀钢 已提交
34 35 36
          if (newImgSize > this.fileSize) {
            console.log('图片尺寸太大!' + fileSize + ' >> ' + newImgSize)
          }
fv2010's avatar
fv2010 已提交
37

何秀钢 已提交
38 39 40
          const blob = this.dataURLtoBlob(newImgData, fileType)
          const nfile = new File([blob], this.file.name)
          resolve(nfile)
fv2010's avatar
fv2010 已提交
41
        }
何秀钢 已提交
42 43 44
      }
    })
  }
fv2010's avatar
fv2010 已提交
45

何秀钢 已提交
46 47 48 49 50 51 52 53
  /**
   * 长宽等比缩小
   * 图像的一边(长或宽)为最大目标值
   */
  dWH(srcW, srcH, dMax) {
    const defaults = {
      width: srcW,
      height: srcH
fv2010's avatar
fv2010 已提交
54
    }
何秀钢 已提交
55 56 57 58 59 60 61 62 63 64 65 66
    if (Math.max(srcW, srcH) > dMax) {
      if (srcW > srcH) {
        defaults.width = dMax
        defaults.height = Math.round(srcH * (dMax / srcW))
        return defaults
      } else {
        defaults.height = dMax
        defaults.width = Math.round(srcW * (dMax / srcH))
        return defaults
      }
    } else {
      return defaults
fv2010's avatar
fv2010 已提交
67
    }
何秀钢 已提交
68
  }
fv2010's avatar
fv2010 已提交
69

何秀钢 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
  fileSizeKB(dataURL) {
    let sizeKB = 0
    sizeKB = Math.round((dataURL.split(',')[1].length * 3 / 4) / 1024)
    return sizeKB
  }

  /**
   * 转为Blob
   */
  dataURLtoBlob(dataURL, fileType) {
    const byteString = atob(dataURL.split(',')[1])
    let mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]
    const ab = new ArrayBuffer(byteString.length)
    const ia = new Uint8Array(ab)
    for (let i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i)
    }
    if (fileType) {
      mimeString = fileType
    }
    return new Blob([ab], { type: mimeString, lastModifiedDate: new Date() })
  }
}