uniapp利用canvas压缩图片

在最近的项目开发中遇到一个问题,在用uniapp开发抖音小程序,进行实名认证上传图片,为了上传图片的速度和体验进行了图片的压缩,在利用官方的api的时候发现了在Android设备中一切正常,压缩的也很小,但是在ios设备中相册选择没问题,但是拍照后压缩api失效,导致上传速度降低!

uni.chooseImage({
    count: 1, //默认9
    sizeType: ['compressed'], //压缩图片
    success: function (res) {
     //拿到压缩后的图片地址,进行二次压缩
        uni.compressImage({
              src: res.tempFiles[0].path, // 图片路径
              quality: 5, // 压缩质量,范围为0 - 100,100为不压缩
              success: (compressRes) => {
                console.log('压缩成功', compressRes);
                // 处理compressRes.tempFilePath即为压缩后的图片路径
              },
              fail: (err) => {
                console.log('压缩失败', err);
              }
            });
    }
});

利用官方的api,一张3-5m的图片 二次压缩后大概得到一张10-30kb的图片,除了在ios设备上拍照情况下,二次压缩失败,图片依旧是500kb左右的图~

这明显不符合业务需求,在官方文档和社区找了半天,依旧没找到解决方法,那么只有最后的解决办法,自己去写压缩图片方法!

我选择的是利用canvas压缩图片

const {width, height} = imageInfo;
const canvasWidth = 300; // 设置Canvas的宽度
const canvasHeight = 400; // 设置Canvas的高度
const ctx = uni.createCanvasContext('photoCanvas', this);
const aspectRatio = width / height;
let drawWidth, drawHeight;
if (aspectRatio > canvasWidth / canvasHeight) {
  drawWidth = canvasWidth;
  drawHeight = canvasWidth / aspectRatio;
} else {
  drawWidth = canvasHeight * aspectRatio;
  drawHeight = canvasHeight;
}
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.drawImage(imageInfo.path, 0, 0, width, height, (canvasWidth - drawWidth) / 2, (canvasHeight - drawHeight) / 2, drawWidth, drawHeight);
ctx.draw(false, () => {
  uni.canvasToTempFilePath({
    canvasId: 'photoCanvas',
    fileType: 'jpg',
    quality: 0.5,
    success: (result) => {
      // 压缩后的图片地址
      console.log('压缩后的图片地址:', result.tempFilePath);
      this.uploadPic(result)
    },
    fail: error => {
      console.log('canvasToTempFilePath失败', error);
    }
  }, this);
});

利用canvas绘制image通过uni.canvasToTempFilePathquality: 0.5 压缩图片质量范围(0-1),通过原图宽高比,压缩等比的图片!如果只写上述代码执行,发现canvas并不执行!

于是我就想着在页面中

<canvas canvas-id="photoCanvas" style="position: absolute; left: -9999px;width: 300px;height: 400px"/>

这种方式可以隐藏canvas又可以使用它压缩图片

需要注意的是 width: 300px;height: 400px" 这个宽高必须要设置,因为canvas 没办法动态设置宽高比如这样

const ctx = uni.createCanvasContext('myCanvas');  
ctx.width = 300 
ctx.height = 400

这种方式是不起作用的,如果不设置宽高,得到的图片本来应该是300*400的,但是实际上得到的却是300*225

总之uniapp的压缩中确实有点坑,在使用上述的方法可以使得图片在Android和ios设备中得到一张10-30k之间的压缩图!

有人会说如果是500kb的图片也不是很大啊? 但是我们开发中需要先把图片转化成base64 然后对整个请求参数进行sm2的加密

require('sm-crypto').sm2.doEncrypt(jsonStr, publicKey)

所以最终在图片上传时的参数翻了一倍,大概是1m左右,而且加密的时长要5-10s秒,整体体验下来不是很好,而压缩后的总时长 才1-3s ,体验翻倍!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容