微信小程序使用Canvas做图片压缩

微信小程序使用Canvas做图片压缩

最近在工作中接触了一个小程序上传图片并将大于500k的图片压缩的需求,由于小程序本身的的压缩功能无法自定义比例,所以决定使用Canvas进行图片压缩。开发过程中也踩了一些坑,因此决定将其分享,如果你也在使用Canvas进行图片压缩的过程中遇到了问题,那么希望本文对你有所帮助。

1.使用Cnavas压缩图片的原理
canvas元素用于在网页上绘制图形,无论你是绘画直线,曲线,文字还是图片,我们使用Canvas做图片压缩,就是用到了它绘制图片这一点。

// 第一步,我们需要在wxml中加上一个Canvas标签
  <view style="hiddenCanvas">
    <canvas canvas-id='myCanvas' class='press-canvas'
      style='width: {{ windowWidth }}px; height: {{ windowWidth }}px;'></canvas>
  </view>


//第二部,我们需要想选择一张图片,想要让Canvas绘制图片,需要先获取图片路径
wx.chooseImage({
        sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
        success: function (res) {
          // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
          that.setData({
            [photoflag + ".loading"]: true
          })//遮罩
          var tempFilePaths = res.tempFilePaths[0];//选择的图片的路径
          let tempFiles = res.tempFiles[0];//选择的图片的大小
          wx.getFileSystemManager().readFile({
            filePath: tempFilePaths,
            encoding: "base64",
            success: res => {
            //这一步是获取base64格式的图片用来上传
              let data = {  base64: res.data };
              //判断获取的图片文件是否大于500k,若大于500k则执行图片压缩方法,若小于则直接上传
              if (tempFiles && (tempFiles.size / 1024 > 500)) {
                //压缩上传
                that.compressImg(tempFilePaths, data that)
              } else {
                //正常上传
                that.uploadImg(data,  that);
              }
            }
          })
        },
      });
//因为本文主要讲解图片压缩,所以上传部分就不写了,接下来就是第三步,使用Canvas压缩图片
 //图片压缩
    compressImg(path, data, that) { //path:未经压缩的图片地址,data:上传的参数 that:当前组件对象
      wx.getImageInfo({
        src: path,
        success: function (res) {
          const ctx = wx.createCanvasContext('myCanvas', that)//画布
          
          let ratio = res.width / res.height;
          ctx.width = 200;
          ctx.height = ctx.width / ratio;
         //这里的三行代码,是根据选择的图片的长宽比例,同比缩放
          
          ctx.drawImage(path, 0, 0, ctx.width, ctx.height)//使用Canvas绘制图片,绘制的图片就是压缩后的图片,我们要做的就是拿到这个压缩后的图片
          
          ctx.draw(true, setTimeout(function () {
            wx.canvasToTempFilePath({
              canvasId: "myCanvas",
              x: 0, y: 0,
              width: ctx.width,
              height: ctx.height,
              success: function (res) {
                console.log("成功获取压缩后文件" + res);
                //到这里就已经拿到了压缩后的图片文件,但是大多数情况下,我们上传的都是base64格式,所以还需要将图片转为base64并上传
                wx.getFileSystemManager().readFile({
                  filePath: res.tempFilePath,
                  encoding: "base64",
                  success: res => {
                    data.base64 = res.data
                    that.uploadImg(data, property, photoflag, that);
                    ctx.draw();//清空画布
                  }
                })
              },
            }, that)
          }, 500))
        }
      })
    },    

2.踩过的坑
做这个功能一共用来2天的时间,百度上的有关这种压缩方式的坑也是五花八门,我只说我遇到的,并附上解决方法。
第一个坑:绘制完压缩图片后,拿不到压缩后的图片
解决方法:ctx.draw的回调中调用wx.canvasToTempFilePath就可以拿到。
第二个坑:ctx.draw的回调不执行
解决方法:在回调函数的外面套一个一次性定时器
第三个坑:进了回调后报错
解决方法:如果你是写在自定义组件中,那么你需要在wx.createCanvasContext(‘myCanvas’, that)和ctx.draw(true,setTimeout(function () {
wx.canvasToTempFilePath({},that)
},时间)中传入当前组件对象,这里去看官方文档就行,官方文档对这两个api都有描述。
第四个坑:传入that后,无任何反应,即success,fail,complete都不进
解决方法:我遇到这个问题的原因是我wxml中的Canvas标签是隐藏的,所以无法找到,但是这个错误是不报错的,所以我很长时间都不明白为什么,到底是哪里写错了才导致了这个问题,解决方法就是不隐藏Canvas标签,如果你不想在页面中看到Canvas标签,可通过CSS解决
.press-canvas {
position: absolute;
top: -1000px;
background-color: gray;
}

3.总结
这就是我在使用Canvas压缩图片过程中遇到的坑,希望能帮助到踩到这个坑的你。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值