
HTML Canvas 채우기와 테두리 그리기
HTML5 Canvas에서 도형을 그릴 때 채우기(fill)와 테두리 그리기(stroke)는 가장 기본적인 작업이다. 이 페이지에서는 두 기능의 사용법과 관련 속성을 알아본다.
기본 개념: 채우기와 테두리
Canvas에서는 두 가지 주요 메소드로 도형을 완성한다:
- fill() – 경로의 내부를 색으로 채운다
- stroke() – 경로의 테두리만 그린다
채우기 색상과 테두리 색상
도형을 그리기 전에 색상을 지정할 수 있다:
- fillStyle – 채우기 색상을 설정한다
- strokeStyle – 테두리 색상을 설정한다
사각형 예제
다음 코드는 채우기와 테두리가 다른 색상인 사각형을 그린다:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.fillStyle = "#FF0000";ctx.fillRect(20, 20, 150, 100);ctx.strokeStyle = "#0000FF";ctx.strokeRect(20, 20, 150, 100);</script>
코드 실행 시 fillStyle을 “#FF0000″(빨간색)으로 설정하고 fillRect(20, 20, 150, 100)로 빨간색 사각형을 그린다. 그 다음 strokeStyle을 “#0000FF”(파란색)으로 설정하고 strokeRect(20, 20, 150, 100)로 같은 위치에 파란색 테두리를 추가한다.
경로를 이용한 도형 그리기
복잡한 도형을 그릴 때는 경로(path)를 사용한다. 다음은 경로를 그리는 기본 단계다:
- beginPath()로 새 경로 시작
- moveTo()로 시작점 설정
- lineTo(), arc() 등으로 경로 그리기
- closePath()로 경로 닫기(선택사항)
- fill() 또는 stroke()로 경로 완성
삼각형 예제
fill()을 사용한 채워진 삼각형:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.beginPath();ctx.moveTo(150, 20);ctx.lineTo(75, 100);ctx.lineTo(225, 100);ctx.closePath();ctx.fillStyle = "green";ctx.fill();</script>
stroke()를 사용한 테두리만 있는 삼각형:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.beginPath();ctx.moveTo(150, 20);ctx.lineTo(75, 100);ctx.lineTo(225, 100);ctx.closePath();ctx.strokeStyle = "purple";ctx.stroke();</script>
도형에 채우기와 테두리 모두 적용하기
같은 도형에 채우기와 테두리를 모두 적용하려면 fill()과 stroke() 메소드를 순서대로 호출하면 된다:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.beginPath();ctx.arc(150, 75, 50, 0, 2 * Math.PI);ctx.fillStyle = "yellow";ctx.fill();ctx.strokeStyle = "black";ctx.lineWidth = 5;ctx.stroke();</script>
💡 중요:
• 채우기와 테두리의 순서가 중요하다. 일반적으로 먼저 fill()을 호출한 후 stroke()를 호출한다.
• stroke()를 먼저 호출하면 채우기 색상이 테두리까지 덮을 수 있다.
그라데이션 채우기
단색 대신 그라데이션으로 도형을 채울 수도 있다. Canvas는 두 가지 유형의 그라데이션을 지원한다:
- 선형 그라데이션(createLinearGradient())
- 원형 그라데이션(createRadialGradient())
선형 그라데이션 예제
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");var grd = ctx.createLinearGradient(0, 0, 300, 0);grd.addColorStop(0, "red");grd.addColorStop(1, "blue");ctx.fillStyle = grd;ctx.fillRect(0, 0, 300, 150);</script>
원형 그라데이션 예제
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");var grd = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);grd.addColorStop(0, "white");grd.addColorStop(1, "green");ctx.fillStyle = grd;ctx.fillRect(0, 0, 300, 150);</script>
패턴 채우기
이미지를 사용하여 반복 패턴으로 도형을 채울 수 있다. createPattern() 메소드를 사용하면 된다:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");var img = new Image();img.src = "https://www.w3schools.com/graphics/paper.gif";img.onload = function() {var pattern = ctx.createPattern(img, "repeat");ctx.fillStyle = pattern;ctx.fillRect(0, 0, 300, 150);}</script>
그림자 효과
Canvas에서는 텍스트와 도형에 그림자를 추가할 수 있다. 다음 속성들을 사용한다:
- shadowColor – 그림자 색상을 설정한다
- shadowBlur – 그림자의 흐림 정도를 설정한다
- shadowOffsetX – 그림자의 수평 거리를 설정한다
- shadowOffsetY – 그림자의 수직 거리를 설정한다
채운 사각형에 그림자 추가:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.shadowColor = "rgba(0, 0, 0, 0.5)";ctx.shadowBlur = 10;ctx.shadowOffsetX = 5;ctx.shadowOffsetY = 5;ctx.fillStyle = "blue";ctx.fillRect(50, 30, 200, 80);</script>
선 스타일과 채우기 스타일
Canvas에서 사용할 수 있는 다양한 선 스타일과 채우기 스타일 속성을 정리했다:
속성 | 설명 | 가능한 값 |
---|---|---|
fillStyle | 채우기 색상 또는 스타일을 설정 | 색상, 그라데이션, 패턴 |
strokeStyle | 테두리 색상 또는 스타일을 설정 | 색상, 그라데이션, 패턴 |
lineWidth | 선의 두께를 설정 | 픽셀 단위의 숫자 |
lineCap | 선 끝의 모양을 설정 | butt, round, square |
lineJoin | 선이 만나는 모서리의 모양을 설정 | bevel, round, miter |
miterLimit | 두 선이 예각으로 만날 때 최대 miter 길이를 설정 | 숫자 |
setLineDash() | 선의 대시 패턴을 설정 | 배열 [실선 길이, 공백 길이, …] |
lineDashOffset | 대시 패턴의 오프셋을 설정 | 픽셀 단위의 숫자 |
채우기 규칙(Fill Rule)
복잡한 경로를 채울 때 어떤 영역을 “내부”로 간주할지 결정하는 규칙이다. Canvas는 두 가지 채우기 규칙을 지원한다:
- “nonzero” – 기본값. 경로가 교차하는 방향에 따라 내부 여부 결정
- “evenodd” – 경로를 교차하는 횟수에 따라 내부 여부 결정
fill() 메소드에 채우기 규칙을 매개변수로 전달할 수 있다:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
<script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.beginPath();ctx.moveTo(50, 20);ctx.lineTo(250, 20);ctx.lineTo(150, 120);ctx.closePath();ctx.moveTo(150, 40);ctx.lineTo(100, 100);ctx.lineTo(200, 100);ctx.closePath();ctx.fillStyle = "blue";ctx.fill("evenodd");</script>
실전 예제: 다양한 채우기와 테두리 조합
다음은 다양한 채우기와 테두리 스타일을 보여주는 예제다:
<canvas id="myCanvas" width="600" height="300" style="border:1px solid #d3d3d3;"><script>var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");ctx.beginPath();ctx.arc(75, 75, 50, 0, Math.PI);ctx.fillStyle = "coral";ctx.fill();ctx.beginPath();ctx.arc(200, 75, 50, 0, 2 * Math.PI);ctx.strokeStyle = "purple";ctx.lineWidth = 5;ctx.stroke();ctx.beginPath();ctx.arc(350, 75, 50, 0, 2 * Math.PI);ctx.fillStyle = "lightblue";ctx.fill();ctx.strokeStyle = "darkblue";ctx.lineWidth = 2;ctx.stroke();var grd = ctx.createLinearGradient(450, 25, 550, 125);grd.addColorStop(0, "yellow");grd.addColorStop(1, "orange");ctx.fillStyle = grd;ctx.fillRect(450, 25, 100, 100);ctx.strokeStyle = "red";ctx.lineWidth = 4;ctx.strokeRect(450, 25, 100, 100);ctx.beginPath();ctx.shadowColor = "rgba(0,0,0,0.7)";ctx.shadowBlur = 10;ctx.shadowOffsetX = 5;ctx.shadowOffsetY = 5;drawStar(ctx, 75, 200, 5, 50, 25);ctx.fillStyle = "gold";ctx.fill();ctx.shadowColor = "transparent";ctx.beginPath();ctx.setLineDash([5, 5]);ctx.strokeStyle = "green";ctx.lineWidth = 2;ctx.strokeRect(150, 175, 100, 100);function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) {var rot = Math.PI / 2 * 3;var x = cx;var y = cy;var step = Math.PI / spikes;ctx.beginPath();ctx.moveTo(cx, cy - outerRadius);for (var i = 0; i < spikes; i++) {x = cx + Math.cos(rot) * outerRadius;y = cy + Math.sin(rot) * outerRadius;ctx.lineTo(x, y);rot += step;x = cx + Math.cos(rot) * innerRadius;y = cy + Math.sin(rot) * innerRadius;ctx.lineTo(x, y);rot += step;}ctx.lineTo(cx, cy - outerRadius);ctx.closePath();}</script>[/code]
💡 성능 팁:
• 여러 개의 채우기와 테두리를 그릴 때는 비슷한 스타일을 그룹화하여 그리면 성능이 향상된다
• 복잡한 그림자는 성능에 영향을 줄 수 있으므로 필요한 경우에만 사용한다
• 대규모 애니메이션에서는 사전 렌더링된 이미지나 패턴을 사용하는 것이 좋다