Files
sam-kd/drawModule.md
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

10 KiB

Drawing Module API 문서

📋 개요

Drawing Module은 웹 브라우저에서 사용할 수 있는 독립적인 Canvas 기반 그리기 도구입니다. 모달 형태의 UI를 제공하며, 다양한 그리기 기능과 이미지 편집 기능을 포함합니다.

🚀 빠른 시작

1. 파일 포함

<!DOCTYPE html>
<html>
<head>
    <!-- Bootstrap CSS (선택사항) -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- Bootstrap Icons (선택사항) -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
    <!-- Drawing Module CSS (필수) -->
    <link href="css/drawingModule.css" rel="stylesheet">
</head>
<body>
    <!-- jQuery (필수) -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- Drawing Module JS (필수) -->
    <script src="js/drawingModule.js"></script>
</body>
</html>

2. 기본 사용법

// 기본 인스턴스 생성
const drawer = new DrawingModule({
    container: 'body',
    onSave: (data) => {
        console.log('저장된 이미지:', data.imageData);
        console.log('저장 시간:', data.timestamp);
    }
});

// 그리기 도구 표시
drawer.show();

📊 API 참조

생성자 (Constructor)

new DrawingModule(options)

옵션 매개변수

옵션 타입 기본값 설명
container string 'body' 모달을 생성할 컨테이너 선택자
width number 800 모달의 전체 너비 (px)
height number 600 모달의 전체 높이 (px)
canvasWidth number 320 캔버스의 실제 너비 (px)
canvasHeight number 240 캔버스의 실제 높이 (px)
title string '그리기 도구' 모달 헤더 제목
initialImage string null 초기에 로드할 이미지 URL 또는 데이터 URL
onSave function null 저장 시 호출되는 콜백 함수
onCancel function null 취소 시 호출되는 콜백 함수

콜백 함수 시그니처

onSave 콜백:

onSave: (data) => {
    // data.imageData - base64 인코딩된 이미지 데이터
    // data.timestamp - 저장 시각 (Date 객체)
    // data.width - 캔버스 너비
    // data.height - 캔버스 높이
}

onCancel 콜백:

onCancel: () => {
    // 사용자가 취소 버튼을 클릭했을 때 호출
}

메서드 (Methods)

show()

그리기 도구 모달을 표시합니다.

drawer.show();

hide()

그리기 도구 모달을 숨깁니다.

drawer.hide();

loadImage(imageUrl)

캔버스에 이미지를 로드합니다.

drawer.loadImage('path/to/image.png');
// 또는 데이터 URL
drawer.loadImage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==');

clear()

캔버스의 모든 내용을 지웁니다.

drawer.clear();

getImageData()

현재 캔버스의 이미지 데이터를 반환합니다.

const imageData = drawer.getImageData();
console.log(imageData); // base64 문자열

🎨 주요 기능

그리기 모드

  • 점연결 (Polyline): 클릭한 점들을 연결하여 선을 그립니다
  • 직선 (Line): 시작점과 끝점을 클릭하여 직선을 그립니다
  • 자유선 (Free): 마우스를 드래그하여 자유롭게 선을 그립니다

추가 기능

  • 직각 모드: 수평/수직선만 그리기 (체크박스로 활성화)
  • 색상 선택: 16진수 컬러 피커로 선 색상 변경
  • 선 굵기 조절: 1-10px 범위의 슬라이더로 선 굵기 조정
  • 지우개: 원형 지우개로 특정 영역 삭제 (크기 조절 가능)
  • 텍스트 추가: 클릭한 위치에 텍스트 입력
  • 실행취소 (Undo): 마지막 작업 되돌리기
  • 초기화: 캔버스의 모든 내용 삭제
  • 터치 지원: 모바일/태블릿 디바이스 터치 이벤트 지원

📱 사용 예제

1. 기본 그리기 도구

const basicDrawer = new DrawingModule({
    container: 'body',
    onSave: (data) => {
        // 이미지를 로컬 저장소에 저장
        localStorage.setItem('drawing', data.imageData);
        alert('그리기가 저장되었습니다!');
    }
});
basicDrawer.show();

2. 커스텀 크기 캔버스

const largeDrawer = new DrawingModule({
    container: '#myContainer',
    canvasWidth: 640,
    canvasHeight: 480,
    title: '큰 캔버스 그리기',
    onSave: (data) => {
        console.log(`캔버스 크기: ${data.width}x${data.height}`);
        downloadImage(data.imageData, 'large-drawing.png');
    }
});
largeDrawer.show();

3. 이미지 편집

const imageEditor = new DrawingModule({
    container: 'body',
    initialImage: '/path/to/existing-image.jpg',
    title: '이미지 편집',
    onSave: (data) => {
        // 편집된 이미지를 서버에 업로드
        uploadImageToServer(data.imageData);
    },
    onCancel: () => {
        console.log('이미지 편집이 취소되었습니다.');
    }
});
imageEditor.show();

4. 서버로 이미지 저장

const drawer = new DrawingModule({
    container: 'body',
    onSave: (data) => {
        // AJAX로 서버에 이미지 전송
        $.ajax({
            url: '/api/save-drawing',
            method: 'POST',
            data: {
                image: data.imageData,
                timestamp: data.timestamp.toISOString(),
                width: data.width,
                height: data.height
            },
            success: function(response) {
                alert('서버에 저장되었습니다!');
                console.log('저장된 이미지 ID:', response.imageId);
            },
            error: function(error) {
                alert('저장에 실패했습니다: ' + error.responseText);
            }
        });
    }
});
drawer.show();

5. 다중 인스턴스

// 동시에 여러 개의 그리기 도구 사용
const drawer1 = new DrawingModule({
    container: 'body',
    title: '그리기 1',
    canvasWidth: 200,
    canvasHeight: 200,
    onSave: (data) => console.log('Drawing 1 saved')
});

const drawer2 = new DrawingModule({
    container: 'body',
    title: '그리기 2',
    canvasWidth: 300,
    canvasHeight: 200,
    onSave: (data) => console.log('Drawing 2 saved')
});

drawer1.show();
setTimeout(() => drawer2.show(), 100); // 약간의 지연

🛠️ 유틸리티 함수

이미지 다운로드 함수

function downloadImage(dataUrl, filename) {
    const link = document.createElement('a');
    link.download = filename;
    link.href = dataUrl;
    link.click();
}

// 사용법
const drawer = new DrawingModule({
    onSave: (data) => {
        downloadImage(data.imageData, 'my-drawing.png');
    }
});

Base64를 Blob으로 변환

function dataURLtoBlob(dataURL) {
    const arr = dataURL.split(',');
    const mime = arr[0].match(/:(.*?);/)[1];
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);

    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }

    return new Blob([u8arr], {type: mime});
}

// 사용법
const drawer = new DrawingModule({
    onSave: (data) => {
        const blob = dataURLtoBlob(data.imageData);
        const formData = new FormData();
        formData.append('image', blob, 'drawing.png');

        // FormData를 서버에 전송
        fetch('/upload', {
            method: 'POST',
            body: formData
        });
    }
});

🎯 파일 구조

project/
├── test_drawing.php          # 테스트 페이지 (PHP)
├── css/
│   └── drawingModule.css     # 스타일시트
├── js/
│   └── drawingModule.js      # 메인 JavaScript 모듈
└── drawModule.md            # 이 문서

🔧 커스터마이징

CSS 커스터마이징

주요 CSS 클래스들을 오버라이드하여 스타일을 변경할 수 있습니다:

/* 모달 배경색 변경 */
.dm-modal {
    background-color: rgba(0, 0, 0, 0.8);
}

/* 버튼 색상 변경 */
.dm-btn-primary {
    background-color: #custom-color;
}

/* 캔버스 테두리 스타일 변경 */
#dmCanvas {
    border: 3px solid #custom-border-color;
}

JavaScript 이벤트 훅

모듈의 동작을 커스터마이징하려면 콜백을 사용하세요:

const drawer = new DrawingModule({
    onSave: (data) => {
        // 저장 전 검증
        if (data.width < 100 || data.height < 100) {
            alert('그림이 너무 작습니다!');
            return;
        }

        // 커스텀 저장 로직
        customSaveFunction(data);
    },
    onCancel: () => {
        // 취소 시 정리 작업
        cleanupResources();
    }
});

🚨 주의사항

  1. jQuery 의존성: 이 모듈은 jQuery에 의존하므로 jQuery를 먼저 로드해야 합니다.

  2. CSS 파일 필수: drawingModule.css 파일이 없으면 UI가 제대로 표시되지 않습니다.

  3. 브라우저 호환성: HTML5 Canvas를 지원하는 브라우저에서만 작동합니다.

  4. 이미지 크기 제한: 매우 큰 캔버스는 브라우저 성능에 영향을 줄 수 있습니다.

  5. 메모리 관리: 여러 인스턴스를 사용할 때는 사용하지 않는 인스턴스를 적절히 정리하세요.

🐛 문제 해결

일반적인 문제들

Q: 모달이 표시되지 않아요. A: CSS 파일이 제대로 로드되었는지, 그리고 show() 메서드를 호출했는지 확인하세요.

Q: 그리기가 작동하지 않아요. A: jQuery가 로드되었는지, 그리고 JavaScript 콘솔에 오류가 없는지 확인하세요.

Q: 이미지 저장이 안 돼요. A: onSave 콜백이 제대로 설정되었는지 확인하세요.

Q: 모바일에서 터치가 작동하지 않아요. A: 최신 버전의 모듈을 사용하고 있는지 확인하세요. 터치 이벤트는 자동으로 처리됩니다.

📄 라이선스

이 모듈은 MIT 라이선스 하에 배포됩니다.

🔄 업데이트 내역

  • v1.0.0: 초기 릴리스
    • 기본 그리기 기능
    • 모달 UI
    • 이미지 로드/저장
    • 터치 지원