记一次用canvas解决图片压缩

788 阅读2分钟

记一次用canvas解决图片压缩

vant-ui upload组件 上传图片自动翻转了

在我们使用 vant-UI的uploader 组件时。

uploader 组件在某些安卓机中出现 :

上传时正着显示的图片,上传之后图片自动90°旋转了。

因此我们需要使用 Exif 插件对图片的信息进行分析。


  npm install exif-js --save

  import Exif from 'exif-js'

  const getOrientation = (file) => {
    return new Promise((resolve) => {
      let Orientation = null
      // 去获取拍照时的信息 ,解决拍出来的照片旋转问题
      Exif.getData(file, () => {
        Orientation = Exif.getTag(file, 'Orientation')
        resolve(Orientation)
      })
    })
  }

图片压缩

图片压缩的思路就是使用canvas的drawImage 将原来较大的图片绘制到新的画布上并且设置大小。

最后将canvas图片通过toBlob方法转化成Bolb , 再使用 window.File() 将Bolb文件转化为真正的File文件。

canvas.toBlob 方法接收3个参数,回调,name, 和压缩比例。因为我们这里是手机端,

我们这里已经对图片的像素大小进行了修改 ,在压缩比例上我们不做太大修改。

以下是整个方法的代码。


// 压缩图片 纠正图片
const passFile = (file, base64) => {
  return new Promise((resolve, reject) => {
    let img = new Image
    let canvas = document.createElement('canvas')
    let ctx = canvas.getContext('2d')
    img.onload = async function () {

      let type = file.type.split('image/')[1],
        name = file.name,
        size = file.size

      //  图怕大小小于1.2Mb原路返回文件
      if (size < 1.2 * 1024 * 1024) {
        resolve(file)
        canvas = null
        return
      }

      // 版本1 为了解决 压缩越来越大  我们固定宽度进行压缩
      // 我们调节比例 在1.2mb以下时我们不压缩 当前大于1.2MB时 ,按宽度 700像素压缩得到
      // 一个合适的比例 :这个比例来自于手机拍照

      let w = 750
      let h = img.height * 750 / img.width

      const getOrientation = (file) => {
        return new Promise((resolve) => {
          let Orientation = null
          // 去获取拍照时的信息 ,解决拍出来的照片旋转问题
          Exif.getData(file, () => {
            Orientation = Exif.getTag(file, 'Orientation')
            resolve(Orientation)
          })
        })
      }

      let Orientation = await getOrientation(file)

      // 所有图都处理成 宽小长高的图片

      if (Orientation && Orientation !== 1) {
        switch (Orientation) {
          case 6:
            canvas.width = h
            canvas.height = w
            ctx.rotate(Math.PI / 2)
            ctx.drawImage(img, 0, -h, w, h)
            break
          case 3:
            canvas.width = w
            canvas.height = h
            ctx.rotate(Math.PI)
            ctx.drawImage(img, -w, -h, w, h)
            break
          case 8:
            canvas.width = h
            canvas.height = w
            ctx.rotate(3 * Math.PI / 2)
            ctx.drawImage(img, -w, 0, w, h)
            break
        }
      } else {
        ctx.drawImage(img, 0, 0, w, h)
      }

      // 压缩优化
      canvas.toBlob(function (res) {
        const Blob2ImageFileForWXBrowser = (obj) => new window.File([obj], `${(new Date).getTime()}.${type}`);
        resolve(Blob2ImageFileForWXBrowser(res))
        canvas = null
      }, name, 0.9)

    }

    img.src = base64

  })
}