在最近的项目开发中遇到一个问题,在用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.canvasToTempFilePath
的quality: 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
,体验翻倍!!