초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
This commit is contained in:
397
drawModule.md
Normal file
397
drawModule.md
Normal file
@@ -0,0 +1,397 @@
|
||||
# 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
|
||||
- 이미지 로드/저장
|
||||
- 터치 지원
|
||||
Reference in New Issue
Block a user