图片压缩有两种方式
第一种:canvas改变图片的尺寸, 重新生成图片即可
第二种:canvas.toDataURL("image/jpeg", quality); 控制quality的值
- 在不改变图片的(尺寸)宽高前提下:
- 默认值得到的图片往往比原图大
- 当
quality在0.2~0.5之间,压缩图片可以最大化,同时图片质量造成影响不大 - 此参数要想有效,图片的
mimeType需要是image/jpeg或者image/webp,其他mimeType值无效。默认压缩质量是0.92
示例
<input type="file" id="upload">
上传格式尺寸限制
//可上传的图片格式
const ACCEPT = ["image/jpg", "image/png", "image/jpeg"];
// 可上传的最大图片容量
const MAXIZE = 8 * 1024 * 1024;
const MAXIZE_STR = "8MB";
选择图片
const upload = document.getElementById("upload");
upload.addEventListener("change", function (e) {
const [file] = e.target.files;
if (!file) {
return;
}
const { type: fileType, size: fileSize } = file;
console.log("压缩前大小:", fileSize)
// 图片类型检查
if (!ACCEPT.includes(fileType)) {
alert("不支持[" + fileType + "]文件类型!");
upload.value = "";
return;
}
// 图片容量检查
if (fileSize > MAXIZE) {
alert(`文件超出${MAXIZE_STR}`);
upload.value = "";
return;
}
// 压缩图片
convertImageToBase64(file, (base64Image) => {
compress(base64Image, uploadToServer)
}
);
});
核心:压缩图片
function compress(base64Image, callback) {
let maxW = 1024;
let maxH = 1024;
const image = new Image();
image.addEventListener("load", function (e) {
let ratio; //图片的压缩比
let needCompress = false; //是否需要压缩
// 比较图片的实际宽高是否超出
if (maxW < image.naturalWidth) {
needCompress = true;
ratio = image.naturalWidth / maxW;
//图片高度也需要等比压缩
maxH = image.naturalHeight / ratio;
} //经过处理后,实际图片的尺寸为 1024 * 576
if (maxH < image.naturalHeight) {
needCompress = true;
ratio = image.naturalHeight / maxH;
maxW = image.naturalWidth / ratio;
} //经过处理后,实际图片的尺寸为 1024 * 576
if (!needCompress) {
maxW = image.naturalWidth;
maxH = image.naturalHeight;
} //如果不需要压缩,需要获取图片的实际尺寸
const canvas = document.createElement("canvas");
canvas.setAttribute("id", "__compress__");
canvas.width = maxW;
canvas.height = maxH;
canvas.style.visibility = "hidden";
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, maxW, maxH);
ctx.drawImage(image, 0, 0, maxW, maxH);
const compressImage = canvas.toDataURL("image/jpeg", 0.85);
callback && callback(compressImage);
const _image = new Image();
_image.src = compressImage;
document.body.appendChild(_image);
canvas.remove();
console.log("压缩比:" + image.src.length / _image.src.length);
});
image.src = base64Image;
document.body.appendChild(image);
}
上传图片
function uploadToServer(compressImage) {
const file = blobToFile(dataURLtoBlob(compressImage))
console.log("压缩后大小:", file.size)
showInfo("压缩后大小:" + file.size / 1024 + "K")
// console.log("upload to server...", compressImage);
}
文件转换方法
将base64转换为blob
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
将blob转换为file
function blobToFile(theBlob, fileName){
theBlob.lastModifiedDate = new Date(); // 文件最后的修改日期
theBlob.name = fileName; // 文件名
return new File([theBlob], fileName, {type: theBlob.type, lastModified: Date.now()});
}
图片转为base64
function convertImageToBase64(file, callback) {
let reader = new FileReader();
reader.addEventListener("load", function (e) {
const base64Image = e.target.result;
callback && callback(base64Image);
reader = null;
});
// 读取文件内容
reader.readAsDataURL(file);
}