一般用于上传头像。部分场景下无需编辑图片,而是只需要将上传的图像转换为字符串。裁剪图片借助于canvas的drawImage方法,将图片的一部分绘制到画布中。
MDN:CanvasRenderingContext2D.drawImage() - Web API 接口参考 | MDN (mozilla.org)
/**
* 输入一张图片,并压缩至 256x256
*/
export const inputImg = async () => {
// 选择图片
const files = await new Promise<FileList | null>((resolve) => {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.onchange = () => resolve(input.files);
input.click();
});
if (!files || !files.length) return;
const file = files[0];
// 将文件对象转换为 URL
const url = await new Promise<string | void>((resolve) => {
const reader = new FileReader();
reader.onload = () => {
const res = reader.result;
if (typeof res !== "string") return resolve();
resolve(res);
};
reader.readAsDataURL(file);
});
if (!url) return;
// 开始压缩图片
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
if (!ctx) return;
const img = new Image();
// 获取图片的原始宽高
const [naturalWidth, naturalHeight] = await new Promise<[number, number]>(
(resolve) => {
img.onload = () => resolve([img.naturalWidth, img.naturalHeight]);
img.src = url;
}
);
// 计算裁剪的起始坐标和裁剪宽高
// 以最小边为基准,裁剪出正方形
const width = Math.min(naturalWidth, naturalHeight);
// 裁剪的起始坐标,以图片中心为基准
const sx = (naturalWidth - width) / 2;
const sy = (naturalHeight - width) / 2;
// 设置 canvas 的宽高为要压缩至的宽高
const canvasWidth = 256;
canvas.width = canvasWidth;
canvas.height = canvasWidth;
ctx.drawImage(img, sx, sy, width, width, 0, 0, canvasWidth, canvasWidth);
return canvas.toDataURL("image/webp");
};