小程序根据尺寸等比压缩图片
小程序根据尺寸等比压缩图片
微信小程序官方文档有「wx.compressImage」接口可以压缩图片,但只能传入压缩质量,不能根据宽高进行压缩,用户在上传文件时如果选择了3000px以上的则比较占用储存的,前台调用加载速度也会影响。
根据搜索网上相关资料,选择使用「canvas」方式进行压缩,其原理及流程如下:
1、获取原始图片的宽高
2、根据传入的压缩宽高(如果为0则不限制)要求,把图片的原始宽高等比缩小,计算出最终压缩后的图片宽高
3、使用小程序文档接口「canvas-2d」,传入图片、宽高绘制到页面中(需用样式隐藏)
4、将「wx.canvasToTempFilePath」将画布保存为图片,生成本地临时路径
已将压缩流程封装为函数,JS代码如下:
compressImage: function(path, width, height, success) {
let that = this;
//获取原图片信息
wx.getImageInfo({
src: path,
success: function (res) {
let canvasRatio = 1.1;
let picWidth = res.width; //图片原始长宽
let picHeight = res.height;
let scale = picHeight / picWidth; //图片原始比例
let type = res.type == 'jpeg' ? 'jpg' : res.type;
if (width == 0 && height > 0) {
picWidth = Math.trunc(height / scale);
picHeight = height;
} else if (width > 0 && height == 0) {
picWidth = width;
picHeight = Math.trunc(width * scale);
} else if (width > 0 && height > 0) {
while (picWidth > width || picHeight > height) {
picWidth = Math.trunc(res.width / canvasRatio)
picHeight = Math.trunc(res.height / canvasRatio)
canvasRatio = canvasRatio + 0.1;
}
}
const query = wx.createSelectorQuery().in(that);
query.select('#compress-canvas').fields({
node: true,
size: true
}).exec((res) => {
try {
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
let dpr = wx.getSystemInfoSync().pixelRatio;
//这里是设置css样式的宽高。
//属性宽高是css样式宽高的dpr倍,兼容不同机型,避免绘制的内容模糊。
that.setData({
canvasWidth: picWidth / dpr,
canvasHeight: picHeight / dpr
})
canvas.width = picWidth;
canvas.height = picHeight;
const img = canvas.createImage()
img.src = path;
img.onload = () => {
ctx.drawImage(img, 0, 0, picWidth, picHeight); //先画出图片
//延迟600ms,避免部分机型未绘制出图片内容就执行保存操作,导致最终的图片是块白色画板。
setTimeout(() => {
wx.canvasToTempFilePath({
quality: 0.8,
fileType: type,
canvas: canvas,
destWidth: picWidth,
destHeight: picHeight,
success: function (res) {
// wx.compressImage({
// src: res.tempFilePath,
// quality: 80,
// success: function (res) {
success(res.tempFilePath);
// }
// })
}
}, that)
}, 600)
}
} catch (e) {
//异常后的操作
console.log(e);
}
})
}
})
}调用方法:
filePath ---- 图片路径
width ---- 需压缩的宽度
height ---- 需压缩的高度
success ---- 压缩成功函数,返回压缩后的图片路径
this.compressImage(filePath, width, height, function(path) {
console.log(path);
})WXML代码:
<view class="compress-con">
<canvas type="2d" id="compress-canvas" class="compress-canvas" style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;"></canvas>
</view>WXSS样式代码:
/* 压缩图片的画布 */
.compress-con{ position: relative; width: 0; height: 0; overflow: hidden; }
.compress-canvas{ position: absolute; z-index: -1; top: 10000rpx; left: 10000rpx; visibility: hidden; }PS:
「wx.canvasToTempFilePath」支持传入导入的图片质量,默认写了0.8,即80。
在微信开发者工具中,画布导出的图片大小会存在异常,可能压缩后比原图还大,在真机实测中则不会出现。
语雀:https://www.yuque.com/docs/share/9a778b7f-f190-4b82-bf28-2f4ddedb65be
密码:pplg
