Canvas 그림판 완전 정리
색상 팔레트, 선굵기 입력, 마우스 드래그 좌표를 연결해 캔버스 그림판을 만드는 흐름입니다.
<div id="palette">
<div class="color" style="background-color:red"></div>
<input type="color" id="colorInput" value="#00ff00">
</div>
<input type="number" id="widthInput" value="1">
<div id="selectedColor"></div>
<div id="mouselocation"></div>
<canvas id="myCanvas" width="500" height="400"></canvas>
<script>
let canvas, context;
let lineWidth, strokeColor;
function init() {
canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousemove", move, false);
canvas.addEventListener("mousedown", down, false);
canvas.addEventListener("mouseup", up, false);
canvas.addEventListener("mouseout", out, false);
}
function draw(curX, curY) {
context.beginPath();
context.lineWidth = lineWidth;
context.strokeStyle = strokeColor;
context.moveTo(startX, startY);
context.lineTo(curX, curY);
context.stroke();
}
</script>
그림판 예제는 HTML 메뉴, CSS 팔레트 배치, JavaScript 드로잉 로직이 분리된 구조입니다. 사용자는 색상과 선굵기를 고르고 캔버스에서 마우스를 드래그해 선을 그립니다.
- menu 영역은 팔레트, 선굵기 입력, 선택 색상 표시, 좌표 표시를 담습니다.
- palette 안의 div.color 요소들은 클릭 가능한 색상 버튼입니다.
- canvas는 실제 선이 그려지는 공간입니다.
- init 함수는 DOM 요소를 찾고 이벤트 리스너를 등록합니다.
팔레트는 여러 개의 div.color에 background-color를 직접 지정한 형태입니다. 각 div는 색상을 보여 주는 동시에 클릭 가능한 선택지 역할을 합니다.
| 요소 | 역할 | 연결 코드 |
|---|---|---|
| div.color | 고정 색상 칩 | getElementsByClassName("color") |
| input type=color | 사용자 지정 색상 | colorInputObj.onchange |
| selectedColor | 현재 선택 색상 표시 | backgroundColor 변경 |
| widthInput | 선굵기 입력 | lineWidth=this.value |
CSS는 menu를 500px 너비의 도구막대로 만들고, palette와 linewidth, selectedColor, mouselocation을 좌우로 배치합니다. float를 쓰는 옛 방식이지만 학습용으로 박스 배치 흐름을 보기 좋습니다.
- div#menu는 도구막대 전체 크기와 테두리를 정합니다.
- div#palette는 색상 칩들이 들어가는 영역입니다.
- div.color는 20x20 크기의 색상 네모입니다.
- input[type=color]는 커스텀 색상 선택 컨트롤입니다.
init은 body onload에서 실행되어 canvas, context, input, 표시 영역을 찾아 전역 변수에 저장합니다. 이 과정을 거쳐야 이후 이벤트 함수들이 같은 객체를 사용할 수 있습니다.
- myCanvas를 찾아 2D context를 얻습니다.
- widthInput 값을 lineWidth 초기값으로 저장합니다.
- colorInput을 찾아 onchange와 onclick을 등록합니다.
- selectedColor 배경을 현재 strokeColor로 칠합니다.
- 모든 color 칩에 onclick 리스너를 붙입니다.
- canvas에 mousemove, mousedown, mouseup, mouseout을 등록합니다.
색상 선택은 두 경로가 있습니다. input type=color에서 고른 값은 e.target.value로 읽고, 팔레트 div에서 고른 색은 e.target.style.backgroundColor로 읽습니다.
colorInputObj.onchange = function (e) {
strokeColor = e.target.value;
selectedColor.style.backgroundColor = strokeColor;
};
colorObjs[i].onclick = function (e) {
strokeColor = e.target.style.backgroundColor;
selectedColor.style.backgroundColor = strokeColor;
};
선굵기는 number input의 onchange에서 lineWidth 전역 변수로 들어갑니다. draw 함수가 실행될 때 context.lineWidth = lineWidth로 실제 선 굵기에 적용됩니다.
그림을 그릴지 여부는 drawing boolean으로 관리합니다. mousedown에서 true, mouseup과 mouseout에서 false가 됩니다.
| 함수 | 역할 | 상태 |
|---|---|---|
| down | 시작 좌표 저장 | drawing = true |
| move | 현재 좌표까지 선을 그림 | drawing일 때만 실행 |
| up | 그리기 종료 | drawing = false |
| out | 캔버스 이탈 처리 | drawing = false |
draw(curX, curY)는 이전 좌표 startX, startY에서 현재 좌표 curX, curY까지 짧은 선을 긋습니다. move 함수가 계속 호출되면서 짧은 선들이 이어져 자유곡선처럼 보입니다.
function draw(curX, curY) {
context.beginPath();
context.lineWidth = lineWidth;
context.strokeStyle = strokeColor;
context.moveTo(startX, startY);
context.lineTo(curX, curY);
context.stroke();
}
move 함수는 마우스 포인터 좌표를 mouselocation 영역에 표시합니다. offsetX와 offsetY는 캔버스 내부 기준 좌표라서 그림 위치와 같은 기준으로 읽을 수 있습니다.
- 마우스가 오른쪽으로 이동하면 offsetX가 증가합니다.
- 마우스가 아래쪽으로 이동하면 offsetY가 증가합니다.
- 표시 영역은 디버깅과 사용자 피드백 역할을 합니다.
- 좌표 표시와 실제 그리기는 같은 move 이벤트에서 처리됩니다.
원문에는 mouseLocationObj 변수와 mouselocation id처럼 대소문자 차이가 있습니다. 브라우저 전역 id 참조로 우연히 동작할 수 있지만, 명확히 document.getElementById("mouselocation")로 맞추는 편이 안전합니다.
| 부분 | 주의 | 권장 |
|---|---|---|
| mouseLocation | id와 대소문자가 다름 | mouselocation으로 통일 |
| selectedColor | 선언 없이 사용될 수 있음 | let selectedColorObj 사용 |
| lineWidth | 문자열 값 | Number 변환 |
| float 레이아웃 | 구식 배치 | flex로 개선 가능 |
| 확장 | 구현 방향 |
|---|---|
| 지우개 | strokeColor를 배경색으로 바꾸거나 clearRect를 사용합니다. |
| 전체 지우기 | 버튼에서 clearRect(0,0,width,height)를 호출합니다. |
| 저장 | canvas.toDataURL로 이미지 데이터를 만듭니다. |
| 터치 지원 | touchstart, touchmove, touchend를 추가합니다. |
| 도형 도구 | 선, 사각형, 원 모드를 추가합니다. |
- body onload에서 init이 실행됩니다.
- canvas id와 getElementById 인수가 일치합니다.
- 모든 color 칩에 클릭 리스너가 등록됩니다.
- mousedown 없이 move만으로는 그려지지 않습니다.
- mouseout에서 drawing을 false로 바꿉니다.
- draw 뒤에는 startX와 startY를 현재 좌표로 갱신합니다.
| 실수 | 문제 | 해결 |
|---|---|---|
| id 대소문자 불일치 | 요소를 못 찾거나 전역 id 참조에 의존합니다. | getElementById 인수와 HTML id를 정확히 맞춥니다. |
| mousedown 없이 그림 | 마우스를 움직이기만 해도 선이 생깁니다. | drawing 상태가 true일 때만 draw합니다. |
| mouseout 처리 생략 | 캔버스 밖으로 나갔다 들어올 때 선이 이어집니다. | mouseout에서 drawing=false를 실행합니다. |
| start 좌표 갱신 누락 | 선이 계속 처음 지점에서 시작됩니다. | move에서 draw 후 startX/startY를 현재 좌표로 바꿉니다. |
| 선 색 표시 미갱신 | 사용자가 선택한 색을 알기 어렵습니다. | selectedColor 배경을 strokeColor와 동기화합니다. |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| 웹 스토리지 실습 완전 정리 (0) | 2026.07.17 |
|---|---|
| 오디오 플레이리스트 완전 정리 (0) | 2026.07.17 |
| JS 비디오 제어 · watchPosition 완전 정리 (0) | 2026.07.16 |
| JS Geolocation 완전 정리 (0) | 2026.07.16 |
| JS 오디오·비디오 제어 완전 정리 (0) | 2026.07.16 |
왕진 블로그

댓글