公司的小程序产品突然让把之前做的压缩图片上传加一个裁剪缩放选中功能。
从微信社区里找了一下,目前最火的image-cropper插件地址
有一说一这款插件的功能文档描述得挺全的(不像某信写的文档),看了一下源码,用的小程序的自定义组件
直接复制组件到compoents里就可以使用了。
不过样式明显不符合自己的需求。经过一番修改最终的效果:
结果项目上线后没几天就有用户反馈上传的图片变模糊了
分析了一下原因,在PS里面绘制非矢量图放大或缩小会损失像素。这里我注意到在生成图片的宽高用的是裁剪框宽高乘以固定的比例,而这里的生成的图片是基于画布绘制不存在矢量图一说,那么当图片的宽度小于裁剪框乘以比例后的宽度,就会被拉伸到同样裁剪框比例的宽度从而导致图片失真并且还会加大图片的体积,同理大图缩小同样会导致图片失真。
那么只要解决生成的图片宽度不被拉伸或缩小就行了,在一开始源码里的pushImg选取图片后就获取图片的宽度,然后通过和裁剪宽相比计算出裁剪框的多少倍可以和图片宽度一样。最后再把这个倍数赋值给export_scale
就可以原图宽高裁剪生成。而这里我想压缩一下图片的质量,只需要再把这个倍数*0.8就可以控制图片压缩到80%
后面的反馈中又发现了一个微信的坑,wx.getImageInfo
在开发工具和某些机型上获取图片宽高,如果图片的原始信息上方向为right或left,会把宽高的值取反导致绘制的图片直接变形。这里需要判断一下方向将宽高改回来
pushImg(src) {
if (src) {
this.setData({
imgSrc: src
});
//发现是手动赋值直接返回,交给watch处理
return;
}
// getImageInfo接口传入 src: '' 会导致内存泄漏
if (!this.data.imgSrc) return;
//获取选取的图片的高度
wx.getImageInfo({
src: this.data.imgSrc,
success: (res) => {
let width = res.width;
this.data.imageObject = JSON.parse(JSON.stringify(res)); // 深拷贝防止同时修改了res
if(res.orientation == 'right' || res.orientation == 'left'){
// 方向旋转了90度图片信息会把宽高取反,需要把宽和高改回来
this.data.imageObject.width = res.height;
width = res.height;
this.data.imageObject.height = res.width;
}
// 原图宽高
let export_scale = width/this.data.width; //调整生成图片的比例
if(width > 2000){
// 如果图片宽度大于2000以上的高清图
this.setData({
export_scale: export_scale*0.3, // 同时渲染画布上绘图比例同时压缩成30%大小
})
} else {
this.setData({
export_scale: export_scale*0.8, // 同时渲染画布上绘图比例同时压缩成80%大小
})
}
//图片非本地路径需要换成本地路径
if (this.data.imgSrc.search(/tmp/) == -1) {
this.setData({
imgSrc: res.path
});
}
//计算最后图片尺寸
this._imgComputeSize();
if (this.data.limit_move) {
//限制移动,不留空白处理
this._imgMarginDetectionScale();
}
this._draw();
},
fail: (err) => {
this.setData({
imgSrc: ''
});
}
});
},
至于后面的一些样式方法直接看image-cropper(修改版)就行了,注意这里是我自己添加的上传图片的方法,可以自行修改