도형 그리기
기본적으로 캔버스 상의 좌표 공간은 아래의 형태를 따릅니다. 좌상단을 기준으로 x, y 좌표를 판단합니다.

직사각형 그리기
캔버스 상에서 직사각형을 그리기는 데에는 세가지 함수가 있습니다.
fillRect(x, y, width, height)
- 색칠된 직사각형을 그립니다.
strokeRect(x, y, width, height)
- 직사각형 윤곽선을 그립니다.
clearRect(x, y, width, height)
- 직사각형 모양으로 해당 부분들을 완전히 지웁니다.
rect(x, y, width, height)
- 직사각형 모양으로 경로를 추가합니다. 이후 좌표가 해당 경로로 이동합니다.
이들을 이용해 하나의 예제를 살펴봅시다.
ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);
경로 그리기
경로는 직사각형 외의 유일한 원시형(primitive) 도형입니다. 경로를 통해 도형을 그리기 위해서는 다음의 단계를 거치게 됩니다.
- 경로를 생성
- 그리기 명령들을 통해 경로 상에 그립니다.
- 그린 경로에 대한 윤곽선을 그리거나 도형 내부를 채웁니다.
이러한 단계들을 수행하게 아래의 함수들이 사용됩니다.
beginPath()
- 새로운 경로를 만듭니다.
- 이후에 계속 살펴보겠지만, 여러 경로들을 설정하기 위해 사용됩니다.
closePath()
- 현재 경로의 시작점과 연결되는 직선을 추가합니다. 이는 옵션 사항입니다.
stroke()
- 윤곽선을 통해 도형을 그립니다.
fill()
- 경로 내부를 채워 색칠된 도형을 그립니다. 이 경우 별도로
closePath()
를 해줄 필요가 없습니다.
이를 통해 간단한 삼각형을 그려봅시다.
ctx.beginPath();
ctx.moveTo(75, 50);
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill();
펜 이동하기
moveTo(x, y)
- 이를 이용하면, 펜을 해당 좌표로 옮기기만 하고, 그리진 않습니다.
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false); // Mouth (clockwise)
ctx.moveTo(65, 65);
ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // Left eye
ctx.moveTo(95, 65);
ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // Right eye
ctx.stroke();
선 그리기
lineTo(x, y)
- 이는 현재 위치에서 해당 좌표 위치까지 선을 그려냅니다.
// Filled triangle
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill();
// Stroked triangle
ctx.beginPath();
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath();
ctx.stroke();
호(Arc) 또는 원 그리기
arc(x, y, radius, startAngle, endAngle, anticlockwise)
- 해당 좌표에, 반지름
radius
를 갖도록startAngle
각도에서endAngle
각도까지anticlockwise
방향으로 호를 그려냅니다.
arcTo(x1, y1, x2, y2, radius)
- 주어진 각 제어점과 반지름으로 호를 그리고, 이전 점과 직선으로 연결합니다.
- 이에 대해서는 여기를 살펴봅시다.
<img src=">
주의!:
arc
함수에서의 각도는 degree가 아닌 radian 단위를 사용합니다. 따라서 degree 단위를 사용하려면 별도의 변환이 요구됩니다.
radians = (Math.PI/180)*degrees
const startAngle = 0;
const endAngle = (Math.PI / 180) * 90;
ctx.beginPath();
ctx.arc(120, 120, 100, startAngle, endAngle, true);
ctx.stroke();
베지어(Bezier) 곡선과 이차(Quadratic) 곡선

베지어 곡선은 주로 복잡한 형태를 그려내는데 사용됩니다.
quadraticCurveTo(cp1x, cp1y, x, y)
cp1x
및cp1y
로 지정된 제어점을 통해 현재 펜 위치에서x
,y
로 지정된 끝점까지 이차 베지어 곡선을 그립니다.
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
- 각 제어점을 통해
x
,y
로 지정된 끝점까지 삼차 베지어 곡선을 그립니다.
ctx.beginPath();
ctx.moveTo(75, 25);
ctx.quadraticCurveTo(25, 25, 25, 62.5);
ctx.quadraticCurveTo(25, 100, 50, 100);
ctx.quadraticCurveTo(50, 120, 30, 125);
ctx.quadraticCurveTo(60, 120, 65, 100);
ctx.quadraticCurveTo(125, 100, 125, 62.5);
ctx.quadraticCurveTo(125, 25, 75, 25);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(75, 40);
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
ctx.fill();
Path2D 오브젝트
Path2D()
new
키워드와 함께 사용되어 새로운Path2D
객체를 반환합니다. 기존 경로 혹은 SVG 경로를 인자로 받을 수도 있습니다.
SVG 경로 데이터를 활용하는 경우, 아래와 같은 형태가 됩니다.
const p = new Path2D('M10 10 h 80 v 80 h -80 Z');
이를 활용하면, 하나의 컨텍스트로 이리저리 옮겨가며 그리던 방식에서 벗어나, 객체의 형태로 각 경로를 변수에 저장할 수 있습니다.
const rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
const circle = new Path2D();
circle.moveTo(125, 35);
circle.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.stroke(rectangle);
ctx.fill(circle);