小程序使用canvas进行图片缩放和压缩

封装了一个插件

使用方式:
html和css部分

 //html页面底部放一个canvas元素
// 隐藏掉canvas
.myCanvas{
    border: solid 1rpx #ccc;
    position: fixed;
    left: -10000rpx;
}

// 下面是js逻辑

let {ImageCompressor} = require("../../../utils/imageCompressor.js") // 引入插件
  onLoad: function (options) {
    // 页面加载后初始化插件,传入必须的参数
    this.imageCompressor =  new ImageCompressor({
      VueComponent:this,
      canvasId:'myCanvas',
    })
  }
  ...
  uploadImg: function () {
    let that = this
    wx.chooseImage({
      count: 9, // 默认9
      sizeType: ["original", "compressed"], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ["album", "camera"], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        如果是多张图片,就调用插件的forEachCompressImg方法把res传进去,回调函数中可以获取到压缩后的图片地址
        that.imageCompressor.forEachCompressImg(res,function(tempFilePath){
          // 拿到压缩后的图片地址后再进行自己的上传逻辑
          that.upload_file(
            __config.basePath + "api/upload.jsp?uid=" + that.data.uid,
            tempFilePath
          )
        })
      },
    })
  },

插件代码,建议放入到util目录下

/**
 * 使用Canvas进行图片缩放和压缩
 * @param {Object} VueComponent vue组件的实例
 * @param {String} canvasId canvas-id
 * @param {Number} imgMaxSize 最大的图片宽高尺寸
 */
export class ImageCompressor {
  constructor(option) {
    this.VueComponent = option.VueComponent || {}
    this.canvasId = option.canvasId || ""
    this.imgMaxSize = option.imgMaxSize || 500
    this.init()
  }
  init() {
    console.log("init done", this)
  }
  /**
   * 批量压缩图片函数
   * @param {Object} res wx.chooseImage返回的res数据对象,通过回调返回压缩后的图片地址
   * @param {Function} callBack
   */
  async forEachCompressImg(res = {}, callBack = {}) {
    let that = this
    for (let [index, item] of res.tempFilePaths.entries()) {
      console.log("-----------------------------------")
      console.log("原始图片size:", res.tempFiles[index].size / 1024 + "k")
      let imgPath = res.tempFilePaths[index]
      let resImg = await that.imgCompress(imgPath)
      wx.getFileInfo({
        filePath: resImg.tempFilePath,
        success(res) {
          console.log("compressImage压缩后的图片size", res.size / 1024 + "k")
        },
      })
      callBack && callBack(resImg.tempFilePath)
    }
  }
  /**
   * 单个图片压缩
   * @param {String} imgSrc 临时图片路径
   */
  imgCompress(imgSrc = "") {
    let that = this
    let VueComponent = this.VueComponent
    return new Promise((resolve, reject) => {
      wx.getImageInfo({
        src: imgSrc,
        success: function (res) {
          //---------利用canvas压缩图片--------------
          var ratio = 2
          var canvasWidth = res.width //图片原始长宽
          var canvasHeight = res.height
          var limit = that.imgMaxSize // 宽高限制
          while (canvasWidth > limit || canvasHeight > limit) {
            // 保证宽高在200以内
            canvasWidth = Math.trunc(res.width / ratio)
            canvasHeight = Math.trunc(res.height / ratio)
            ratio++
          }
          VueComponent.setData({
            cWidth: canvasWidth,
            cHeight: canvasHeight,
          })
          var ctx = wx.createCanvasContext(that.canvasId, VueComponent)
          ctx.drawImage(res.path, 0, 0, canvasWidth, canvasHeight)
          ctx.draw(
            false,
            setTimeout(function () {
              console.log(2, "压缩前图片地址", res.path)
              wx.canvasToTempFilePath({
                canvasId: that.canvasId,
                destWidth: canvasWidth,
                destHeight: canvasHeight,
                quality: 0.5, // 压缩倍率
                fileType: "jpg",
                success: function (res) {
                  resolve(res)
                },
                fail: function (res) {
                  reject(res.errMsg)
                },
              })
            }, 300) //延迟500ms,避免部分机型未绘制出图片内容就执行保存操作,导致最终的图片是块白色画板。
          )
        },
        fail: function (res) {
          reject(res.errMsg)
        },
      })
    })
  }
}