需求:
按照比例压缩图片宽高(这里设置为1200px,图片宽或高其中超过1200px就进行压缩,可以自己设置值),压缩后的图片转成base64格式,一次性提交到后台
平台兼容说明:
利用canvas压缩图片的方式兼容微信小程序、H5和App端。但图片转base64各端的实现是不一致的,需要注意的是,canvas压缩图片在H5端输出的图片格式就是base64,所以H5端无需进行转换
为了方便,这里用的是uView的Upload组件,组件文档参考Upload组件
<view class="compress">
<form @submit="formSubmit">
<u-upload ref="Upload" :auto-upload="false" :show-progress="false" width="200" height="200"></u-upload>
<view class="uni-btn-v u-m-t-80"><button form-type="submit" class="submit">提交</button></view>
</form>
<canvas class="canvas" :style="{ width: `${cWidth}px`, height: `${cHeight}px` }" canvas-id="myCanvas"></canvas>
</view>
export default {
data() {
return {
cWidth: 200, //设置canvas画布的宽
cHeight: 200 //设置canvas画布的高
}
}
}
这里采用手动上传的方式,通过ref获取上传图片列表
methods: {
//获取图片信息
async formSubmit() {
let imgList = [];
this.list = this.$refs.Upload.lists; //获取图片列表
for (let i = 0; i < this.list.length; i++) {
let item = this.list[i];
let img = await this.imageToBase64(item); //调用图片转base64的方法
imgList.push(img);
}
}
}
微信小程序使用官方提供的的uni.getFileSystemManager(仅适用于小程序端)获取文件管理器 ,具体文档见uni.getFileSystemManager。再通过FileSystemManager.readFile读取本地文件内容,具体文档见FileSystemManager.readFile
App端采用plus.io.resolveLocalFileSystemURL(),具体文档详见 App扩展规范 HTML5 Plus
//图片转base64
imageToBase64(item) {
return new Promise(async (resolve, reject) => {
let res = await this.compressImage(item); // 调用压缩图片的方法,先压缩图片,再转base64
//#ifdef MP-WEIXIN
uni.getFileSystemManager().readFile({
filePath: res.tempFilePath,
encoding: 'base64',
success: function(data) {
resolve(data.data);
}
});
//#endif
//#ifdef H5
let url = res.tempFilePath.replace(/^data:image\/\w+;base64,/, '');
resolve(url);
//#endif
// #ifdef APP-PLUS
plus.io.resolveLocalFileSystemURL(res.tempFilePath, function(entry) {
entry.file(function(file) {
let fileReader = new plus.io.FileReader();
fileReader.readAsDataURL(file);
fileReader.onloadend = function(evt) {
let url = evt.target.result.replace('/^data:image\/\w+;base64,/', '');
resolve(url);
};
});
});
// #endif
});
}
上面调用了compressImage方法压缩图片,下面就来看看如何压缩图片
//压缩图片
compressImage(item) {
return new Promise(async (resolve, reject) => {
let info = await this.getImageInfo(item.url); // 获取图片信息,获取到图片的宽高,当图片宽度或高度其中一个超过设置的最大值时,就把对应的宽高设置成最大值(这里设置为1200),然后另一边按等比例进行缩放
let maxWidth = 1200;
let maxHeight = 1200;
let canvasWidth = info.width; //图片实际宽度
let canvasHeight = info.height; //图片实际高度
let scale = 1;
if (canvasWidth > maxWidth) {
scale = canvasWidth / maxWidth;
canvasWidth = maxWidth;
canvasHeight = Math.floor(canvasHeight / scale);
}
if (canvasHeight > maxHeight) {
scale = canvasHeight / maxHeight;
canvasHeight = maxHeight;
canvasWidth = Math.floor(canvasWidth / scale);
}
this.cWidth = canvasWidth;
this.cHeight = canvasHeight;
// 绘制canvas
let ctx = uni.createCanvasContext('myCanvas', this);
//清除画布
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
//绘制图片
ctx.drawImage(info.path, 0, 0, canvasWidth, canvasHeight);
ctx.draw(
false,
setTimeout(() => {
//导出图片路径
uni.canvasToTempFilePath({
canvasId: 'myCanvas', // 画布标识:canvas-id
width: canvasWidth,
height: canvasHeight,
destWidth: canvasWidth, //输出图片宽度
destHeight: canvasHeight, //输出图片高度
fileType: 'jpg', //目标文件的类型
success: res => {
resolve(res);
},
fail: err => {
reject(err);
console.log('err:', err);
}
});
})
);
});
},
//获取图片信息
getImageInfo(url) {
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: url,
success: info => {
resolve(info);
},
fail: err => {
console.log('err:', err);
}
});
});
},
至此,前端压缩图片就完成啦~