API 参考
为希望集成或扩展图像裁剪器 (Image Cropper) 功能的开发者提供的技术参考。
提供图像裁剪界面的主 Vue 组件。
<template>
<ImageCropper
:aspect-ratio="aspectRatio"
:output-format="format"
:quality="quality"
@crop-complete="handleCropComplete"
/>
</template>
| 属性 | 类型 | 默认值 | 描述 |
|---|
aspectRatio | number | 'free' | 'free' | 裁剪宽高比限制 |
outputFormat | 'png' | 'jpeg' | 'webp' | 'png' | 输出图像格式 |
quality | number[] | [85] | JPEG 质量 (10-100) |
maxWidth | number | undefined | 最大输出宽度 |
maxHeight | number | undefined | 最大输出高度 |
| 事件 | 载荷 | 描述 |
|---|
crop-complete | CropResult | 裁剪完成时触发 |
image-loaded | ImageInfo | 源图像加载完成时触发 |
error | Error | 发生错误时触发 |
interface CropResult {
url: string; // 裁剪后图像的 Blob URL
blob: Blob; // 图像 Blob 数据
canvas: HTMLCanvasElement; // Canvas 元素
info: {
width: number; // 输出宽度 (像素)
height: number; // 输出高度 (像素)
size: number; // 文件大小 (字节)
format: string; // 输出格式
};
}
interface ImageInfo {
width: number; // 原始宽度
height: number; // 原始高度
size: number; // 文件大小 (字节)
type: string; // MIME 类型
name: string; // 原始文件名
}
interface CropSettings {
aspectRatio: number | "free";
outputFormat: "png" | "jpeg" | "webp";
quality: number;
outputWidth?: number;
outputHeight?: number;
}
const cropperOptions = {
aspectRatio: NaN, // 自由宽高比
viewMode: 1, // 将裁剪框限制在画布内
responsive: true, // 响应式裁剪器
restore: false, // 调整大小后不恢复
guides: true, // 显示虚线
center: true, // 显示中心指示器
highlight: false, // 不高亮裁剪区域
cropBoxMovable: true, // 允许移动裁剪框
cropBoxResizable: true, // 允许调整裁剪框大小
toggleDragModeOnDblclick: false, // 禁用双击切换
};
| 方法 | 参数 | 返回值 | 描述 |
|---|
getCroppedCanvas() | options? | HTMLCanvasElement | 将裁剪区域作为画布获取 |
setAspectRatio() | ratio: number | void | 更改宽高比 |
reset() | - | void | 重置为原始状态 |
destroy() | - | void | 销毁裁剪器实例 |
// 从文件加载图像
function loadImageFromFile(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target?.result as string);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// 将 blob 下载为文件
function downloadBlob(blob: Blob, filename: string): void {
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
// 将画布转换为 blob
function canvasToBlob(canvas: HTMLCanvasElement, format: string, quality?: number): Promise<Blob> {
return new Promise((resolve) => {
canvas.toBlob(resolve, `image/${format}`, quality);
});
}
// 获取图像尺寸
function getImageDimensions(src: string): Promise<{ width: number; height: number }> {
return new Promise((resolve) => {
const img = new Image();
img.onload = () =>
resolve({
width: img.naturalWidth,
height: img.naturalHeight,
});
img.src = src;
});
}
// 格式化文件大小以供显示
function formatFileSize(bytes: number): string {
const sizes = ["Bytes", "KB", "MB", "GB"];
if (bytes === 0) return "0 Bytes";
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i];
}
// 验证图像文件
function isValidImageFile(file: File): boolean {
return file.type.startsWith("image/");
}
- Canvas API: 用于图像操作
- File API: 用于处理文件上传
- Blob API: 用于生成结果
- URL.createObjectURL: 用于图像预览
- Clipboard API: 用于复制功能 (可选)
| 功能 | Chrome | Firefox | Safari | Edge |
|---|
| 核心功能 | ✅ 50+ | ✅ 52+ | ✅ 10+ | ✅ 79+ |
| WebP 输出 | ✅ 32+ | ✅ 65+ | ✅ 14+ | ✅ 79+ |
| 剪贴板 API | ✅ 66+ | ✅ 63+ | ✅ 13.1+ | ✅ 79+ |
// 文件验证错误
class InvalidFileTypeError extends Error {
constructor() {
super("Invalid file type. Please select an image file.");
}
}
// 内存错误
class ImageTooLargeError extends Error {
constructor() {
super("Image is too large to process in this browser.");
}
}
// 处理错误
class CropProcessingError extends Error {
constructor(message: string) {
super(`Crop processing failed: ${message}`);
}
}
// 优雅的错误处理
function handleCropError(error: Error): void {
if (error instanceof InvalidFileTypeError) {
// 显示文件类型错误信息
showErrorMessage("Please select a valid image file");
} else if (error instanceof ImageTooLargeError) {
// 建议减小图像大小
showErrorMessage("Image too large. Please use a smaller image");
} else {
// 通用错误处理
showErrorMessage("An error occurred. Please try again");
}
}
// 清理资源
function cleanup(): void {
// 撤销 blob URL
blobUrls.forEach((url) => URL.revokeObjectURL(url));
// 销毁裁剪器实例
if (cropper) {
cropper.destroy();
cropper = null;
}
// 清除画布引用
canvasRefs.length = 0;
}
// 高效处理大图像
function processLargeImage(canvas: HTMLCanvasElement): HTMLCanvasElement {
const maxDimension = 4096; // 浏览器限制
const scale = Math.min(maxDimension / canvas.width, maxDimension / canvas.height, 1);
if (scale < 1) {
const scaledCanvas = document.createElement("canvas");
scaledCanvas.width = canvas.width * scale;
scaledCanvas.height = canvas.height * scale;
const ctx = scaledCanvas.getContext("2d");
ctx.drawImage(canvas, 0, 0, scaledCanvas.width, scaledCanvas.height);
return scaledCanvas;
}
return canvas;
}