w

API 참조

이미지 크롭퍼(Image Cropper) 기능을 통합하거나 확장하려는 개발자를 위한 기술 참조 문서입니다.

핵심 컴포넌트

ImageCropper 컴포넌트

이미지 크롭 인터페이스를 제공하는 메인 Vue 컴포넌트입니다.

<template>
  <ImageCropper
    :aspect-ratio="aspectRatio"
    :output-format="format"
    :quality="quality"
    @crop-complete="handleCropComplete"
  />
</template>

속성 (Props)

속성타입기본값설명
aspectRationumber | 'free''free'크롭 종횡비 제한
outputFormat'png' | 'jpeg' | 'webp''png'출력 이미지 형식
qualitynumber[][85]JPEG 품질 (10-100)
maxWidthnumberundefined최대 출력 너비
maxHeightnumberundefined최대 출력 높이

이벤트 (Events)

이벤트페이로드설명
crop-completeCropResult크롭이 완료될 때 발생
image-loadedImageInfo소스 이미지가 로드될 때 발생
errorError에러가 발생할 때 발생

타입 정의

CropResult

interface CropResult {
  url: string; // 크롭된 이미지의 Blob URL
  blob: Blob; // 이미지 Blob 데이터
  canvas: HTMLCanvasElement; // Canvas 요소
  info: {
    width: number; // 출력 너비 (픽셀)
    height: number; // 출력 높이 (픽셀)
    size: number; // 파일 크기 (바이트)
    format: string; // 출력 형식
  };
}

ImageInfo

interface ImageInfo {
  width: number; // 원본 너비
  height: number; // 원본 높이
  size: number; // 파일 크기 (바이트)
  type: string; // MIME 타입
  name: string; // 원본 파일명
}

CropSettings

interface CropSettings {
  aspectRatio: number | "free";
  outputFormat: "png" | "jpeg" | "webp";
  quality: number;
  outputWidth?: number;
  outputHeight?: number;
}

Cropper.js 통합

설정 옵션

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: numbervoid종횡비 변경
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/");
}

브라우저 호환성

필수 API

  • Canvas API: 이미지 조작용
  • File API: 파일 업로드 처리용
  • Blob API: 결과 생성용
  • URL.createObjectURL: 이미지 미리보기용
  • Clipboard API: 복사 기능용 (선택 사항)

브라우저 지원

기능ChromeFirefoxSafariEdge
핵심 기능✅ 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;
}
이 페이지가 도움이 되었나요?