여러분이 사용하고 계신 브라우저는 HTML5를 지원하지 않기 때문에 몇몇 요소가 제대로 보이도록 JScript를 사용하고 있습니다. 하지만 여러분의 브라우저 설정에서 스크립트 기능이 꺼져있으므로, 현재 페이지를 제대로 확인하시려면 스크립트 기능을 켜주셔야 합니다. HTML Canvas - 채우기 및 선

HTML Canvas – 채우기 및 선

2일전 작성

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)를 사용한다. 다음은 경로를 그리는 기본 단계다:

  1. beginPath()로 새 경로 시작
  2. moveTo()로 시작점 설정
  3. lineTo(), arc() 등으로 경로 그리기
  4. closePath()로 경로 닫기(선택사항)
  5. 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]
💡 성능 팁:
• 여러 개의 채우기와 테두리를 그릴 때는 비슷한 스타일을 그룹화하여 그리면 성능이 향상된다
• 복잡한 그림자는 성능에 영향을 줄 수 있으므로 필요한 경우에만 사용한다
• 대규모 애니메이션에서는 사전 렌더링된 이미지나 패턴을 사용하는 것이 좋다

참고
Mingg`s Diary
밍구
공부 목적 블로그