h5实现图片压缩
使用Canvas API压缩图片
通过Canvas的drawImage和toDataURL方法实现图片压缩。创建一个隐藏的Canvas元素,将图片绘制到Canvas上,再转换为指定质量的Base64或Blob数据。
function compressImage(file, quality = 0.8) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
canvas.toBlob(
(blob) => resolve(blob),
'image/jpeg',
quality
);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
}
控制图片尺寸
在Canvas绘制前限制最大宽度/高度,保持比例缩放。添加尺寸限制参数可避免大图直接压缩导致的体积控制不精确。

function resizeImage(img, maxWidth, maxHeight) {
let width = img.width;
let height = img.height;
if (width > maxWidth) {
height = Math.round((height * maxWidth) / width);
width = maxWidth;
}
if (height > maxHeight) {
width = Math.round((width * maxHeight) / height);
height = maxHeight;
}
return { width, height };
}
使用EXIF.js处理旋转
部分手机拍摄的照片含有EXIF旋转信息,需使用exif-js库读取方向参数,并在Canvas绘制前进行校正。
EXIF.getData(img, function() {
const orientation = EXIF.getTag(this, 'Orientation');
if (orientation === 6) {
[canvas.width, canvas.height] = [canvas.height, canvas.width];
ctx.rotate(Math.PI/2);
ctx.drawImage(img, 0, -canvas.height);
}
});
多格式输出支持
根据需求选择输出格式,toBlob支持JPEG/PNG格式,toDataURL可指定MIME类型。JPEG适合照片类压缩,PNG适合需要透明度的图像。

// PNG格式(无质量参数)
canvas.toBlob(resolve, 'image/png');
// WebP格式(需浏览器支持)
canvas.toBlob(resolve, 'image/webp', 0.8);
分阶段压缩策略
采用"先尺寸后质量"的两阶段压缩:先通过尺寸缩放降低像素总量,再通过质量参数控制编码损失。这种策略比单纯调整质量参数更高效。
// 第一阶段:尺寸缩放到目标大小
const { width, height } = resizeImage(img, 1024, 1024);
canvas.width = width;
canvas.height = height;
// 第二阶段:质量压缩
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(resolve, 'image/jpeg', 0.7);
使用Web Worker优化性能
对于批量压缩或大文件处理,可将Canvas操作放入Web Worker避免阻塞主线程。注意需将Blob数据转换为Transferable对象传输。
// worker.js
self.onmessage = (e) => {
const { imageData, quality } = e.data;
createImageBitmap(imageData).then(img => {
const canvas = new OffscreenCanvas(img.width, img.height);
// ...压缩逻辑
canvas.convertToBlob({ type: 'image/jpeg', quality })
.then(blob => self.postMessage(blob));
});
};






