본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

Canvas 그림판 완전 정리

by 왕진 2026. 7. 16.
반응형

 

 

Canvas Painter

Canvas 그림판 완전 정리

색상 팔레트, 선굵기 입력, 마우스 드래그 좌표를 연결해 캔버스 그림판을 만드는 흐름입니다.

0 오늘 분석할 코드
<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>
palette사용자가 선택할 색상 목록 영역입니다.
color개별 색상 칩 div입니다.
input color사용자가 직접 색을 고르는 폼 컨트롤입니다.
lineWidth캔버스 선 굵기 속성입니다.
strokeStyle캔버스 선 색상 속성입니다.
offsetX캔버스 내부 기준 마우스 x좌표입니다.
offsetY캔버스 내부 기준 마우스 y좌표입니다.
drawing현재 드래그로 그림을 그리고 있는지 나타내는 상태값입니다.

1 그림판 예제의 구조

그림판 예제는 HTML 메뉴, CSS 팔레트 배치, JavaScript 드로잉 로직이 분리된 구조입니다. 사용자는 색상과 선굵기를 고르고 캔버스에서 마우스를 드래그해 선을 그립니다.

  • menu 영역은 팔레트, 선굵기 입력, 선택 색상 표시, 좌표 표시를 담습니다.
  • palette 안의 div.color 요소들은 클릭 가능한 색상 버튼입니다.
  • canvas는 실제 선이 그려지는 공간입니다.
  • init 함수는 DOM 요소를 찾고 이벤트 리스너를 등록합니다.

2 팔레트 HTML

팔레트는 여러 개의 div.color에 background-color를 직접 지정한 형태입니다. 각 div는 색상을 보여 주는 동시에 클릭 가능한 선택지 역할을 합니다.

요소 역할 연결 코드
div.color 고정 색상 칩 getElementsByClassName("color")
input type=color 사용자 지정 색상 colorInputObj.onchange
selectedColor 현재 선택 색상 표시 backgroundColor 변경
widthInput 선굵기 입력 lineWidth=this.value

3 CSS 배치 읽기

CSS는 menu를 500px 너비의 도구막대로 만들고, palette와 linewidth, selectedColor, mouselocation을 좌우로 배치합니다. float를 쓰는 옛 방식이지만 학습용으로 박스 배치 흐름을 보기 좋습니다.

  • div#menu는 도구막대 전체 크기와 테두리를 정합니다.
  • div#palette는 색상 칩들이 들어가는 영역입니다.
  • div.color는 20x20 크기의 색상 네모입니다.
  • input[type=color]는 커스텀 색상 선택 컨트롤입니다.

 

반응형

 

4 init 함수 역할

init은 body onload에서 실행되어 canvas, context, input, 표시 영역을 찾아 전역 변수에 저장합니다. 이 과정을 거쳐야 이후 이벤트 함수들이 같은 객체를 사용할 수 있습니다.

  1. myCanvas를 찾아 2D context를 얻습니다.
  2. widthInput 값을 lineWidth 초기값으로 저장합니다.
  3. colorInput을 찾아 onchange와 onclick을 등록합니다.
  4. selectedColor 배경을 현재 strokeColor로 칠합니다.
  5. 모든 color 칩에 onclick 리스너를 붙입니다.
  6. canvas에 mousemove, mousedown, mouseup, mouseout을 등록합니다.

5 색상 선택 처리

색상 선택은 두 경로가 있습니다. 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;
};

6 선굵기 처리

선굵기는 number input의 onchange에서 lineWidth 전역 변수로 들어갑니다. draw 함수가 실행될 때 context.lineWidth = lineWidth로 실제 선 굵기에 적용됩니다.

input.value는 문자열이므로 계산을 더 붙일 예정이라면 Number(widthInput.value)로 바꾸는 편이 더 안전합니다.

7 마우스 드로잉 상태

그림을 그릴지 여부는 drawing boolean으로 관리합니다. mousedown에서 true, mouseup과 mouseout에서 false가 됩니다.

함수 역할 상태
down 시작 좌표 저장 drawing = true
move 현재 좌표까지 선을 그림 drawing일 때만 실행
up 그리기 종료 drawing = false
out 캔버스 이탈 처리 drawing = false

8 draw 함수

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();
}

9 좌표 표시

move 함수는 마우스 포인터 좌표를 mouselocation 영역에 표시합니다. offsetX와 offsetY는 캔버스 내부 기준 좌표라서 그림 위치와 같은 기준으로 읽을 수 있습니다.

  • 마우스가 오른쪽으로 이동하면 offsetX가 증가합니다.
  • 마우스가 아래쪽으로 이동하면 offsetY가 증가합니다.
  • 표시 영역은 디버깅과 사용자 피드백 역할을 합니다.
  • 좌표 표시와 실제 그리기는 같은 move 이벤트에서 처리됩니다.

10 오타와 구조 점검

원문에는 mouseLocationObj 변수와 mouselocation id처럼 대소문자 차이가 있습니다. 브라우저 전역 id 참조로 우연히 동작할 수 있지만, 명확히 document.getElementById("mouselocation")로 맞추는 편이 안전합니다.

부분 주의 권장
mouseLocation id와 대소문자가 다름 mouselocation으로 통일
selectedColor 선언 없이 사용될 수 있음 let selectedColorObj 사용
lineWidth 문자열 값 Number 변환
float 레이아웃 구식 배치 flex로 개선 가능

11 확장 아이디어
확장 구현 방향
지우개 strokeColor를 배경색으로 바꾸거나 clearRect를 사용합니다.
전체 지우기 버튼에서 clearRect(0,0,width,height)를 호출합니다.
저장 canvas.toDataURL로 이미지 데이터를 만듭니다.
터치 지원 touchstart, touchmove, touchend를 추가합니다.
도형 도구 선, 사각형, 원 모드를 추가합니다.

12 검증 체크리스트
  • body onload에서 init이 실행됩니다.
  • canvas id와 getElementById 인수가 일치합니다.
  • 모든 color 칩에 클릭 리스너가 등록됩니다.
  • mousedown 없이 move만으로는 그려지지 않습니다.
  • mouseout에서 drawing을 false로 바꿉니다.
  • draw 뒤에는 startX와 startY를 현재 좌표로 갱신합니다.

M 자주 하는 실수
실수 문제 해결
id 대소문자 불일치 요소를 못 찾거나 전역 id 참조에 의존합니다. getElementById 인수와 HTML id를 정확히 맞춥니다.
mousedown 없이 그림 마우스를 움직이기만 해도 선이 생깁니다. drawing 상태가 true일 때만 draw합니다.
mouseout 처리 생략 캔버스 밖으로 나갔다 들어올 때 선이 이어집니다. mouseout에서 drawing=false를 실행합니다.
start 좌표 갱신 누락 선이 계속 처음 지점에서 시작됩니다. move에서 draw 후 startX/startY를 현재 좌표로 바꿉니다.
선 색 표시 미갱신 사용자가 선택한 색을 알기 어렵습니다. selectedColor 배경을 strokeColor와 동기화합니다.

핵심 한 줄 요약

palette색상 칩과 color input은 strokeColor를 바꾸는 두 가지 입력 경로입니다.
mousemousedown, mousemove, mouseup, mouseout이 그림판 드래그의 핵심 이벤트입니다.
canvas짧은 선을 계속 이어 그리면 자유곡선 그림판이 됩니다.

Tags

#Canvas#JavaScript#그림판#palette#mousemove#mousedown#lineWidth#strokeStyle#offsetX#티스토리
▼ 티스토리 태그 입력란 복사용
Canvas, JavaScript, 그림판, palette, mousemove, mousedown, lineWidth, strokeStyle, offsetX, 티스토리
반응형

댓글