一、原理:实际上就是利用canvas进行重新绘制
1、先将图片的file文件转成baseURL
2、创建一个image标签去接收文件获取图片的宽高和比例。
3、创建canvas画布设置画布的大小。
4、将图片绘制到canvas上面。
5、对canvas进行压缩处理,获得新的baseURL
6、将baseURL转化回文件。
二、核心代码
/**
* 压缩图片
* @param file 压缩文件
* @param compressThreshold 开启压缩的阈值,默认 5M
* @param openCompress 是否开启压缩,默认 true
* @param pictureQuality 压缩比,默认 0.92
* @returns
*/
export const compressFile = (
file: File,
compressThreshold = 5,
openCompress = true,
pictureQuality = 0.92
) => {
console.log('========== Entry Compress File Function ==========');
console.log('before compress file: ', file);
//判断是否是图片类型
const isAccept = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'].includes(file.type);
if (isAccept) {
const fileSize = file.size / 1024 / 1024;
console.log('before compress, the file size is : ', fileSize.toFixed(2) + ' M');
//当开启图片压缩且图片大小大于等于压缩阈值,进行压缩
if (fileSize >= compressThreshold && openCompress) {
//判断浏览器内核是否支持base64图片压缩
if (typeof FileReader === 'undefined') {
return file;
} else {
try {
return new Promise(resolve => {
//声明FileReader文件读取对象
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
// 生成canvas画布
const canvas = document.createElement('canvas');
// 生成img
// const img = document.createElement('img');
const img = new Image();
img.src = reader.result as any;
img.onload = () => {
const ctx = canvas.getContext('2d');
//原始图片宽度、高度
const originImageWidth = img.width,
originImageHeight = img.height;
//默认最大尺度的尺寸限制在(1920 * 1080)
const maxWidth = 1920,
maxHeight = 1080,
ratio = maxWidth / maxHeight;
//目标尺寸
let targetWidth = originImageWidth,
targetHeight = originImageHeight;
//当图片的宽度或者高度大于指定的最大宽度或者最大高度时,进行缩放图片
if (originImageWidth > maxWidth || originImageHeight > maxHeight) {
//超过最大宽高比例
if (originImageWidth / originImageHeight > ratio) {
//宽度取最大宽度值maxWidth,缩放高度
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originImageHeight / originImageWidth));
} else {
//高度取最大高度值maxHeight,缩放宽度
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originImageWidth / originImageHeight));
}
}
// canvas对图片进行缩放
canvas.width = targetWidth;
canvas.height = targetHeight;
// 清除画布
ctx?.clearRect(0, 0, targetWidth, targetHeight);
// 绘制图片
ctx?.drawImage(img, 0, 0, targetWidth, targetHeight);
// quality值越小,图像越模糊,默认图片质量为0.92
const imageDataURL = canvas.toDataURL(file.type || 'image/jpeg', pictureQuality);
// 去掉URL的头,并转换为byte
const imageBytes = window.atob(imageDataURL.split(',')[1]);
// 处理异常,将ascii码小于0的转换为大于0
const arrayBuffer = new ArrayBuffer(imageBytes.length);
const uint8Array = new Uint8Array(arrayBuffer);
for (let i = 0; i < imageBytes.length; i++) {
uint8Array[i] = imageBytes.charCodeAt(i);
}
const mimeType = imageDataURL?.split(',')?.[0]?.match(/:(.*?);/)?.[1];
const newFile = new File([uint8Array], file.name, {
type: mimeType || 'image/jpeg'
});
console.log(
'after compress, the file size is : ',
(newFile.size / 1024 / 1024).toFixed(2) + 'M'
);
console.log('after compress file: ', newFile);
resolve(newFile);
};
};
reader.onerror = () => {
return file;
};
})
.then(res => {
return res;
})
.catch(() => {
return file;
});
} catch (e) {
//压缩出错,直接返回原file对象
return file;
}
}
} else {
//不需要压缩,直接返回原file对象
return file;
}
} else {
//非图片文件,不进行压缩,直接返回原file对象
return file;
}
};
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/64441.html