- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
397 lines
10 KiB
Markdown
397 lines
10 KiB
Markdown
# Drawing Module API 문서
|
|
|
|
## 📋 개요
|
|
|
|
Drawing Module은 웹 브라우저에서 사용할 수 있는 독립적인 Canvas 기반 그리기 도구입니다. 모달 형태의 UI를 제공하며, 다양한 그리기 기능과 이미지 편집 기능을 포함합니다.
|
|
|
|
## 🚀 빠른 시작
|
|
|
|
### 1. 파일 포함
|
|
|
|
```html
|
|
<!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. 기본 사용법
|
|
|
|
```javascript
|
|
// 기본 인스턴스 생성
|
|
const drawer = new DrawingModule({
|
|
container: 'body',
|
|
onSave: (data) => {
|
|
console.log('저장된 이미지:', data.imageData);
|
|
console.log('저장 시간:', data.timestamp);
|
|
}
|
|
});
|
|
|
|
// 그리기 도구 표시
|
|
drawer.show();
|
|
```
|
|
|
|
## 📊 API 참조
|
|
|
|
### 생성자 (Constructor)
|
|
|
|
```javascript
|
|
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 콜백:**
|
|
```javascript
|
|
onSave: (data) => {
|
|
// data.imageData - base64 인코딩된 이미지 데이터
|
|
// data.timestamp - 저장 시각 (Date 객체)
|
|
// data.width - 캔버스 너비
|
|
// data.height - 캔버스 높이
|
|
}
|
|
```
|
|
|
|
**onCancel 콜백:**
|
|
```javascript
|
|
onCancel: () => {
|
|
// 사용자가 취소 버튼을 클릭했을 때 호출
|
|
}
|
|
```
|
|
|
|
### 메서드 (Methods)
|
|
|
|
#### show()
|
|
그리기 도구 모달을 표시합니다.
|
|
|
|
```javascript
|
|
drawer.show();
|
|
```
|
|
|
|
#### hide()
|
|
그리기 도구 모달을 숨깁니다.
|
|
|
|
```javascript
|
|
drawer.hide();
|
|
```
|
|
|
|
#### loadImage(imageUrl)
|
|
캔버스에 이미지를 로드합니다.
|
|
|
|
```javascript
|
|
drawer.loadImage('path/to/image.png');
|
|
// 또는 데이터 URL
|
|
drawer.loadImage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==');
|
|
```
|
|
|
|
#### clear()
|
|
캔버스의 모든 내용을 지웁니다.
|
|
|
|
```javascript
|
|
drawer.clear();
|
|
```
|
|
|
|
#### getImageData()
|
|
현재 캔버스의 이미지 데이터를 반환합니다.
|
|
|
|
```javascript
|
|
const imageData = drawer.getImageData();
|
|
console.log(imageData); // base64 문자열
|
|
```
|
|
|
|
## 🎨 주요 기능
|
|
|
|
### 그리기 모드
|
|
- **점연결 (Polyline)**: 클릭한 점들을 연결하여 선을 그립니다
|
|
- **직선 (Line)**: 시작점과 끝점을 클릭하여 직선을 그립니다
|
|
- **자유선 (Free)**: 마우스를 드래그하여 자유롭게 선을 그립니다
|
|
|
|
### 추가 기능
|
|
- **직각 모드**: 수평/수직선만 그리기 (체크박스로 활성화)
|
|
- **색상 선택**: 16진수 컬러 피커로 선 색상 변경
|
|
- **선 굵기 조절**: 1-10px 범위의 슬라이더로 선 굵기 조정
|
|
- **지우개**: 원형 지우개로 특정 영역 삭제 (크기 조절 가능)
|
|
- **텍스트 추가**: 클릭한 위치에 텍스트 입력
|
|
- **실행취소 (Undo)**: 마지막 작업 되돌리기
|
|
- **초기화**: 캔버스의 모든 내용 삭제
|
|
- **터치 지원**: 모바일/태블릿 디바이스 터치 이벤트 지원
|
|
|
|
## 📱 사용 예제
|
|
|
|
### 1. 기본 그리기 도구
|
|
|
|
```javascript
|
|
const basicDrawer = new DrawingModule({
|
|
container: 'body',
|
|
onSave: (data) => {
|
|
// 이미지를 로컬 저장소에 저장
|
|
localStorage.setItem('drawing', data.imageData);
|
|
alert('그리기가 저장되었습니다!');
|
|
}
|
|
});
|
|
basicDrawer.show();
|
|
```
|
|
|
|
### 2. 커스텀 크기 캔버스
|
|
|
|
```javascript
|
|
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. 이미지 편집
|
|
|
|
```javascript
|
|
const imageEditor = new DrawingModule({
|
|
container: 'body',
|
|
initialImage: '/path/to/existing-image.jpg',
|
|
title: '이미지 편집',
|
|
onSave: (data) => {
|
|
// 편집된 이미지를 서버에 업로드
|
|
uploadImageToServer(data.imageData);
|
|
},
|
|
onCancel: () => {
|
|
console.log('이미지 편집이 취소되었습니다.');
|
|
}
|
|
});
|
|
imageEditor.show();
|
|
```
|
|
|
|
### 4. 서버로 이미지 저장
|
|
|
|
```javascript
|
|
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. 다중 인스턴스
|
|
|
|
```javascript
|
|
// 동시에 여러 개의 그리기 도구 사용
|
|
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); // 약간의 지연
|
|
```
|
|
|
|
## 🛠️ 유틸리티 함수
|
|
|
|
### 이미지 다운로드 함수
|
|
|
|
```javascript
|
|
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으로 변환
|
|
|
|
```javascript
|
|
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 클래스들을 오버라이드하여 스타일을 변경할 수 있습니다:
|
|
|
|
```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 이벤트 훅
|
|
|
|
모듈의 동작을 커스터마이징하려면 콜백을 사용하세요:
|
|
|
|
```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
|
|
- 이미지 로드/저장
|
|
- 터치 지원 |