Canvas API 기초
우리는 9장를 통해 Fetch API
로 서버와 통신하고, 로컬/세션 스토리지
로 클라이언트 데이터를 관리하며, History API
로 SPA의 라우팅을 구현하는 등 웹 애플리케이션의 동적인 상호작용 및 내비게이션 기능을 학습했습니다. 이제 웹 페이지를 더욱 시각적으로 풍부하고 인터랙티브하게 만들 수 있는 강력한 브라우저 기능 중 하나인 Canvas API에 대해 알아볼 차례입니다.
Canvas API는 HTML5에 도입된 <canvas>
요소를 사용하여 웹 페이지에서 2D 그래픽을 직접 그릴 수 있도록 해주는 JavaScript API입니다. 픽셀 단위로 이미지를 조작하거나, 도형, 텍스트, 애니메이션 등을 자유롭게 렌더링할 수 있습니다. 이는 정적인 이미지로는 표현하기 어려운 동적인 시각화, 간단한 게임, 이미지 편집기, 데이터 시각화(차트 등) 등 다양한 분야에서 활용됩니다.
이번 장에서는 Canvas API의 기본적인 사용법, 즉 캔버스 요소 준비부터 컨텍스트 가져오기, 그리고 선, 사각형, 원, 텍스트 등 다양한 도형을 그리는 방법까지 상세히 다루겠습니다.
Canvas API 개요 및 <canvas>
요소
Canvas
는 말 그대로 '도화지'와 같습니다. HTML 문서에는 <canvas>
라는 빈 도화지 요소를 배치하고, 실제 그림은 JavaScript 코드를 사용하여 이 도화지 위에 그리는 방식입니다.
<canvas>
요소 준비
HTML 문서에 <canvas>
태그를 추가하여 그림을 그릴 공간을 정의합니다. width
와 height
속성으로 캔버스의 크기를 지정할 수 있습니다. (CSS로 크기를 조절할 수도 있지만, 렌더링 품질에 영향을 줄 수 있으므로 HTML 속성으로 고정 크기를 지정하는 것이 좋습니다.)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas API 기초</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f0f0f0;
margin: 0;
}
canvas {
border: 2px solid #333; /* 캔버스 경계를 시각적으로 보여주기 위함 */
background-color: #fff;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="500" height="300">
이 브라우저는 Canvas를 지원하지 않습니다.
</canvas>
<script src="canvas-script.js"></script>
</body>
</html>
렌더링 컨텍스트 가져오기
<canvas>
요소 자체는 그림을 그릴 수 있는 인터페이스를 직접 제공하지 않습니다. 그림을 그리기 위해서는 렌더링 컨텍스트(Rendering Context) 를 얻어야 합니다. 가장 흔히 사용되는 것은 2D 그래픽을 위한 '2d'
컨텍스트입니다.
// canvas-script.js
const canvas = document.getElementById('myCanvas');
// getContext() 메서드를 사용하여 렌더링 컨텍스트를 가져옵니다.
const ctx = canvas.getContext('2d');
// 캔버스가 정상적으로 초기화되었는지 확인
if (ctx) {
console.log("2D 렌더링 컨텍스트를 성공적으로 가져왔습니다.");
// 이제 ctx 객체를 사용하여 그림을 그릴 수 있습니다.
} else {
console.error("이 브라우저는 Canvas 2D 컨텍스트를 지원하지 않습니다.");
}
ctx
(Context) 객체는 캔버스에 도형, 텍스트, 이미지 등을 그리는 데 필요한 모든 메서드와 속성을 가지고 있습니다.
기본적인 도형 그리기
Canvas에서 그림을 그리는 과정은 보통 다음과 같습니다.
- 경로 시작:
ctx.beginPath()
로 새로운 그림 경로를 시작합니다. - 경로 정의:
moveTo()
,lineTo()
,arc()
,rect()
등으로 경로를 정의합니다. - 그림 그리기:
stroke()
로 선을 그리거나,fill()
로 도형을 채웁니다. - (선택) 경로 닫기:
closePath()
로 현재 경로를 시작점으로 연결하여 닫습니다.
선(Lines) 그리기
// 선의 색상 설정
ctx.strokeStyle = 'blue';
// 선의 두께 설정
ctx.lineWidth = 5;
// 첫 번째 선: (50, 50)에서 (200, 50)까지
ctx.beginPath(); // 새로운 경로 시작
ctx.moveTo(50, 50); // 시작점 이동
ctx.lineTo(200, 50); // (200, 50)까지 선 그리기
ctx.stroke(); // 경로를 따라 선 그리기 (stroke)
// 두 번째 선: (200, 50)에서 (200, 150)까지
// beginPath()를 다시 호출하면 이전 경로와 독립적으로 그림
ctx.beginPath();
ctx.moveTo(200, 50);
ctx.lineTo(200, 150);
ctx.stroke();
// 삼각형 그리기
ctx.strokeStyle = 'red';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(300, 100);
ctx.lineTo(350, 200);
ctx.lineTo(250, 200);
ctx.closePath(); // 시작점으로 경로를 닫아 삼각형 완성
ctx.stroke();
사각형(Rectangles) 그리기
사각형을 그리는 전용 메서드가 있습니다.
ctx.rect(x, y, width, height)
: 사각형 경로를 정의ctx.strokeRect(x, y, width, height)
: 윤곽선 사각형 그리기ctx.fillRect(x, y, width, height)
: 채워진 사각형 그리기ctx.clearRect(x, y, width, height)
: 지정된 영역을 투명하게 지우기
// 채워진 사각형 (fillStyle 설정)
ctx.fillStyle = 'green'; // 채울 색상 설정
ctx.fillRect(50, 100, 100, 50); // (x, y, width, height)
// 윤곽선 사각형 (strokeStyle, lineWidth 설정)
ctx.strokeStyle = 'purple';
ctx.lineWidth = 3;
ctx.strokeRect(200, 100, 100, 50);
// 특정 영역 지우기
ctx.clearRect(70, 110, 60, 30); // 초록색 사각형의 일부를 지움
원(Arcs/Circles) 그리기
arc()
메서드를 사용하여 원 또는 호를 그립니다.
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise)
x, y
: 원의 중심 좌표radius
: 반지름startAngle, endAngle
: 호의 시작 및 끝 각도 (라디안 단위)counterclockwise
:true
면 반시계 방향,false
면 시계 방향 (기본값)
// 라디안 계산: Math.PI는 파이 (180도)
// 전체 원: 0부터 2 * Math.PI
// 반원: 0부터 Math.PI
// 채워진 원
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.arc(150, 230, 40, 0, 2 * Math.PI, false); // (x, y, 반지름, 시작각, 끝각, 반시계방향)
ctx.fill();
// 윤곽선 원
ctx.strokeStyle = 'darkblue';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.arc(350, 230, 40, 0, 2 * Math.PI, false);
ctx.stroke();
// 반원 (파이차트 조각처럼)
ctx.fillStyle = 'lightblue';
ctx.beginPath();
ctx.moveTo(400, 50); // 중심점에서 시작
ctx.arc(400, 50, 40, 0, Math.PI, false); // 오른쪽 절반 원
ctx.closePath(); // 시작점으로 다시 돌아와 닫음 (채우려면 필요)
ctx.fill();
텍스트(Text) 그리기
텍스트를 그리는 메서드와 스타일 속성이 있습니다.
ctx.fillText(text, x, y, maxWidth)
: 채워진 텍스트 그리기ctx.strokeText(text, x, y, maxWidth)
: 윤곽선 텍스트 그리기
텍스트 스타일 속성
ctx.font
: 폰트 스타일 (예:'48px serif'
)ctx.textAlign
: 텍스트 정렬 ('left'
,'right'
,'center'
,'start'
,'end'
)ctx.textBaseline
: 텍스트 기준선 ('alphabetic'
,'top'
,'hanging'
,'middle'
,'ideographic'
,'bottom'
)
ctx.fillStyle = 'black';
ctx.font = '30px Arial'; // 폰트 크기와 패밀리
ctx.textAlign = 'center'; // 수평 정렬
ctx.textBaseline = 'middle'; // 수직 정렬
// 캔버스 중앙에 텍스트 그리기
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
ctx.fillText('Hello Canvas!', centerX, centerY);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 1;
ctx.font = '20px Sans-serif';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.strokeText('Web Graphics', 10, 10);
경로(Paths) 상태 저장 및 복원
캔버스 컨텍스트의 현재 그리기 상태(색상, 선 두께, 변형 등)를 저장하고 나중에 복원할 수 있습니다. 이는 복잡한 그림을 그릴 때 매우 유용합니다.
ctx.save()
: 현재 그리기 상태를 스택에 저장합니다.ctx.restore()
: 스택의 가장 최근 상태를 복원합니다.
// 기본 상태: 빨간색, 두께 2
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 50, 50); // (0,0)에 빨간색 사각형
ctx.save(); // 현재 상태 저장 (빨간색, 두께 2)
ctx.fillStyle = 'blue'; // 새로운 상태: 파란색
ctx.fillRect(60, 0, 50, 50); // (60,0)에 파란색 사각형
ctx.save(); // 현재 상태 저장 (파란색, 두께 2)
ctx.fillStyle = 'green'; // 새로운 상태: 초록색
ctx.fillRect(120, 0, 50, 50); // (120,0)에 초록색 사각형
ctx.restore(); // 스택에서 가장 최근 상태 복원 (파란색)
ctx.fillRect(180, 0, 50, 50); // (180,0)에 파란색 사각형
ctx.restore(); // 스택에서 다음 상태 복원 (빨간색)
ctx.fillRect(240, 0, 50, 50); // (240,0)에 빨간색 사각형
save()
와 restore()
는 색상, 선 스타일, 그림자, 변형(이동, 회전, 크기 조절) 등 모든 컨텍스트 속성들을 저장하고 복원합니다.
Canvas API 활용 분야
- 게임 개발: 2D 게임 엔진이나 캐주얼 게임 개발에 널리 사용됩니다.
- 데이터 시각화: 차트(막대 그래프, 파이 차트, 선 그래프 등)나 복잡한 통계 데이터를 시각적으로 표현하는 데 활용됩니다 (예: Chart.js).
- 이미지 편집: 이미지 필터 적용, 크롭, 회전, 그림 그리기 등의 기능 구현.
- 애니메이션: 프레임 단위로 그림을 지우고 다시 그리면서 동적인 애니메이션 효과를 만듭니다.
- 사용자 정의 UI 컴포넌트: SVG만으로는 부족한 복잡한 그래픽이 필요할 때 사용됩니다.
마무리하며
이번 장에서는 HTML5에 도입된 강력한 웹 그래픽 도구인 Canvas API의 기초를 심도 있게 학습했습니다.
여러분은 <canvas>
요소를 HTML에 추가하고, JavaScript에서 getContext('2d')
를 통해 2D 렌더링 컨텍스트를 얻는 방법을 배웠습니다. 그리고 이 컨텍스트(ctx
) 객체를 사용하여 선, 사각형, 원과 같은 기본적인 도형을 그리는 방법(beginPath()
, moveTo()
, lineTo()
, stroke()
, fill()
, arc()
, fillRect()
등)과 텍스트를 그리는 방법(fillText()
, strokeText()
, font
, textAlign
등)을 익혔습니다. 또한, save()
와 restore()
를 사용하여 그리기 상태를 효율적으로 관리하는 방법도 살펴보았습니다.
Canvas API는 웹 페이지에서 정적인 이미지로는 표현하기 어려운 복잡하고 동적인 그래픽을 직접 제어할 수 있는 무한한 가능성을 제공합니다. 앞으로 여러분이 웹 게임, 데이터 시각화, 인터랙티브 아트 등 다양한 분야에 도전할 때 이 Canvas API 지식이 큰 자산이 될 것입니다. 직접 다양한 도형을 그려보고, 색상을 변경하며 Canvas의 매력을 느껴보세요.