图片压缩流程
- 使用input或上传组件读取到图片文件file ,使用FileReader将其转换为 base64 编码;
- 创建Image对象,读取转化后的base64;
- 创建canvas ,将新创建的图片画到canvas上;
- 利用 canvas.toDataURL/toBlob 将canvas对象转换为 base64 或 Blob;
- 最后将 base64 或 Blob 转化为 File返回;
toDataURL介绍
canvas的toDataURL()方法是返回一个包含图片展示的 数据URL。可以使用 type 参数其类型,默认为png格式。图片的分辨率为96dpi。
canvas.toDataURL(type, encoderOptions);
type指定转换为base64编码后图片的格式,如:image/png、image/jpeg、image/webp等等,默认为image/png格式;encoderOptions用于设置转换为base64编码后图片的质量,取值范围为0-1,超出取值范围用默认值0.92代替;
返回值是一个数据url,是base64组成的图片的源数据、可以直接赋值给图片的src属性。
/**
* 压缩图片方法
* @param {file} file 文件或文件数组
* @param {Number} quality 图片质量(取值0-1之间默认0.92)
*/
const compressImg = (file, quality) => {
if (Array.isArray(file)) {
// 处理图片数组
return Promise.all(Array.from(file).map((e) => compressImg(e, quality)));
} else {
let qualitys = 1;
//单位:MB
let fileSize = parseInt((file.size / 1024 / 1024).toFixed(2));
if (1 < fileSize && fileSize < 5) {
qualitys = 0.92;
}
if (5 < fileSize && fileSize < 10) {
qualitys = 0.85;
}
if (10 < fileSize) {
qualitys = 0.52;
}
if (quality) {
qualitys = quality;
}
return new Promise((resolve) => {
// 压缩质量大于等于1不处理
if (qualitys >= 1) {
resolve(file);
} else {
// 读取原来的文件类型,不是图片类型不处理
let fileType = file.type;
if (!fileType || !fileType.includes("image/")) {
resolve(file);
return;
}
const fileReader = new FileReader(); // 创建 FileReader
fileReader.onload = ({ target: { result: src } }) => {
const image = new Image(); // 创建 img 元素
image.onload = () => {
// 创建 canvas 元素
const mCanvas = document.createElement("canvas");
const mCtx = mCanvas.getContext("2d");
let targetWidth = image.width;
let targetHeight = image.height;
let originWidth = image.width;
let originHeight = image.height;
if (1 <= fileSize) {
let maxWidth = 1400;
let maxHeight = 1400;
if (5 < fileSize) {
maxWidth = 1920;
maxHeight = 1920;
}
targetWidth = originWidth;
targetHeight = originHeight;
// 图片尺寸超过的限制
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)
);
}
}
}
mCanvas.width = targetWidth;
mCanvas.height = targetHeight;
mCtx.clearRect(0, 0, targetWidth, targetHeight);
// 将图片画到canvas上
mCtx.drawImage(image, 0, 0, targetWidth, targetHeight);
const canvasURL = mCanvas.toDataURL(fileType, qualitys);
const buffer = atob(canvasURL.split(",")[1]);
let length = buffer.length;
const bufferArray = new Uint8Array(new ArrayBuffer(length));
while (length--) {
bufferArray[length] = buffer.charCodeAt(length);
}
const miniFile = new File([bufferArray], file.name, {
type: fileType
});
resolve(miniFile);
};
image.src = src;
};
fileReader.readAsDataURL(file);
}
});
}
};