JavaScript实现图片压缩

图片等比缩小的方法

图片压缩的基本思路

压缩图片主要利用了canvastoBlob方法, toBlob方法可以将canvas画布的画面转换成Blob对象, 同时设置质量

  1. 获取input数据, 使用fileReader转换成 dataUrl

  2. dataUrl的值赋给imagesrc

  3. image绘制进canvas, 注意这里可以对图片尺寸进行控制

  4. 使用canvas.toBlob获取 blob 对象, 可以在其中设置压缩比例

  5. 上传图片

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 上传图片压缩的步骤
// 1. 获取input数据, 使用fileReader转换成dataUrl
// 2. 将dataUrl的值赋给image的src
// 3. 将image绘制进canvas
// 4. 使用canvas.toBlob获取blob对象, 可以在其中设置压缩比例
// 5. 上传图片

const fileToImg = (file: File): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
const img = new Image();
// 将传进来的file转换成dataURl
reader.readAsDataURL(file);
reader.onload = () => {
img.src = reader.result as string;
};
reader.onerror = e => {
reject(e);
};
img.onload = () => {
resolve(img);
};
img.onerror = e => {
reject(e);
};
});
};

const imgToBlob = (
img: HTMLImageElement,
maxWidth: number,
maxHeight: number,
quality: number,
type = "image/png",
): Promise<Blob> => {
return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

// 获取图片原始尺寸
const { width: originWidth, height: originHeight } = img;
// 确定目标尺寸
let targetWidth = originWidth,
targetHeight = originHeight;
// 如果图片尺寸大于目标尺寸, 那么就进行等比缩放
if (targetWidth > maxWidth || targetHeight > maxHeight) {
// 等比缩小的算法
// 如果是横着的图, 图片的宽等于最大宽度, 高等比缩放;
// 如果是竖着的图, 图片的高等于最大高度, 宽等比缩放;
// 先判断是横着的图还是竖着的图
if (targetWidth > targetHeight) {
//横着的
targetWidth = maxWidth;
targetHeight = targetHeight * (maxWidth / originWidth);
} else {
//竖着的
targetHeight = maxHeight;
targetWidth = targetWidth * (maxHeight / originHeight);
}
}
try {
// 把img绘制进canvas
canvas.width = targetWidth;
canvas.height = targetHeight;
ctx?.clearRect(0, 0, targetWidth, targetHeight);
ctx?.drawImage(img, 0, 0, targetWidth, targetHeight);
// 获取blob对象
canvas.toBlob(
blob => {
if (blob) {
resolve(blob);
} else {
reject(new Error("转换失败"));
}
},
type,
quality,
);
} catch (error) {
reject(error);
}
});
};

const inp = document.querySelector("#input");
inp?.addEventListener("change", async e => {
const inputEle = e.target as HTMLInputElement;
if (inputEle.files?.length) {
const img = await fileToImg(inputEle.files[0]);
const blob = await imgToBlob(img, 1000, 1000, 0.2);
console.log(blob);
}
});
作者

cuicui

发布于

2023-02-03

更新于

2023-04-23

许可协议

评论