前俩天做了一个
图片转base64
上传的
功能,发现如果
图片的base64过大的话,请求会变的很慢,严重的直接超时了,所以想到了在
上传前压缩一下
图片,然后再
上传到
后台,这样可以大大的提高效率,在这里记录一下利用 canvas 压缩
图片遇到的几个坑。完整
代码会在文末给出。
第一个坑,在压缩
图片的时候没
获取图片本身的宽高,给了一个 600*480 的定宽定高,因为是手机端的,在
上传图片的时候都是几兆的
图片,所以这块没任何问题。出问题的地方在
修改头像的时候,测试的时候
上传的
图片都是小
图片,然后就出现了 压缩后的
图片显示不完全,大部分都是空白的现象,这就是因为在压缩的时候没有考虑
图片原本的宽高的情况。
第二个坑,
解决第一个坑的办法就是在
图片加载完成后(onload),
获取图片本身的宽高,然后赋值给 canvas,这样进行操作,但是这有个坑就是,
图片加载是异步的,在你 return 的时候,返回的可能是 undefined 而不是你需要的 压缩后的 base64。这里的
解决方法是,新建一个 Promise ,然后把结果 resolve() 返回去,在
调用的时候 .then() 得到结果。
知识点:
canvas 的 toDataURL('image/png',0.9) ; 把 canvas 画的
图片转换为 base64,第一个参数表示的是
图片的类型,第二个参数表示的是
图片的清晰度。
规定一个最大尺寸,如果
图片本身的宽高大于这个尺寸,按照最大的一个边进行缩放,另一个根据
图片的 比例 进行设置,然后设置给 canvas .
miniImage.js
export default async function miniSize(imgData,maxSize = 200*1024){
// const maxSize = 200 * 1024;
if(imgData && imgData.files && imgData.files.size < maxSize) {
return imgData.url;
}else{
console.log('----------------压缩图片-------------------');
const canvas = document.createElement('canvas');
let img = new Image();
img.src = imgData.url;
let ctx = canvas.getContext('2d');
return new Promise((resolve =>{
img.addEventListener('load',function(){
//
图片原始尺寸
let originWidth = this.width;
let originHeight = this.height;
// 最大尺寸限制
let maxWidth = 400,maxHeight = 400;
// 目标尺寸
let targetWidth = originWidth,targetHeight = originHeight;
//
图片尺寸超过400x400的限制
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
// 更宽,按照宽度限定尺寸
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
canvas.width = targetWidth;
canvas.height = targetHeight;
ctx.drawImage(img,targetWidth,targetHeight);
let base64 = canvas.toDataURL('image/png',0.9);
resolve(base64);
},false);
}))
}
}