canvas 태그 - 기본 도형 그리기

너구리오리·2021년 7월 26일
1

HTML canvas 태그

이번 포스트에서는 웹 페이지에 픽셀 그림을 그릴 수 있는 캔버스<canvas> 에 대해 알아보겠습니다.

<canvas> 태그는 정해진 크기의 드로잉 영역 안에 렌더링 컨텍스트rendering contexts를 출력합니다. 우리는 이 컨텍스트를 통해 여러 점의 좌표를 지정하고, 선 또는 면으로 그림을 표현할 수 있습니다.

이번 시리즈에서는 여러 컨텍스트 중 2D 컨텍스트만 다룰 예정입니다. 최종적으로는 HTML 태그에 CSS 스타일을 적용하고 JS 스크립트를 통해 그림판을 구현하는 과정까지 진행해보겠습니다.

최종 결과물 예시 미리보기

canvas 크기 지정하기

<canvas id="tutorial" width="350" height="250"></canvas>

<canvas> 태그는 위 예시처럼 사용합니다. <img> 태그와 비슷하지만 닫는 태그가 있어야 합니다. 가로 세로 길이는 px 단위로 적어주시면 됩니다.

여기서 크기를 지정할 때 아래처럼 HTML이 아닌 CSS에서 정할 수도 있습니다.

// HTML 에서 정의
<canvas id="tutorial" class="canvas"></canvas>

// CSS 에서 크기와 배경색 지정
.canvas {
    width: 700px;
    height: 700px;
    background-color: white;
}

위와 같이 class를 지정하면 여러 CSS 스타일을 적용할 수 있습니다.

한편 주의할 점은 JS 스크립트와 함께 사용할 경우, JS 스크립트에서도 크기를 지정해주어야 합니다.

컨텍스트 가져오기

앞서 canvas를 정의할 때 id를 tutorial로 지정했습니다.

스크립트에서 해당 canvas와 컨텍스트를 가져오려면 아래와 같은 코드가 필요합니다.
2D 컨텍스트를 사용할 것이기 때문에 2D만 가져옵니다.

var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d');

Stroke와 Fill

이제 기본적인 선과 도형을 그려볼 차례입니다.

캔버스에서는 기본 도형을 딱 하나만 지원하는데요, 바로 직사각형입니다.
(걱정마세요. 다른 도형을 그릴 수 없다는 뜻은 아닙니다.)

직사각형을 그릴 수 있는 함수는 아래 세 가지가 있습니다.

fillRect(x, y, width, height)
: 내부가 색칠된 직사각형을 그립니다.
strokeRect(x, y, width, height)
: 직사각형의 윤곽선을 그립니다.
clearRect(x, y, width, height)
: 직사각형을 그리고 내부 영역을 지웁니다. 지워진 부분은 완전히 투명해집니다.

여기서 x와 y는 직사각형의 왼쪽 위 꼭지점의 좌표, width와 height는 그 점으로부터 수평/수직으로 정해지는 너비와 높이입니다.

이때 각 함수명의 Rect은 직사각형인데, fill/stroke/clear의 차이는 무엇일까요?
fill은 내부를 모두 채우는 함수,
stroke은 내부를 채우지 않고 외곽 선만 그리는 함수,
clear는 말 그대로 지우는 함수입니다.

캔버스 그리드

드로잉을 할 때 좌표를 사용하게 되는데, 이때 원점은 어디일까요?
바로 왼쪽 좌상단이 원점입니다. 따라서 width와 height도 자연스럽게 아래 그림처럼 정의됩니다.

Path 그리기

이제 직사각형이 아닌 도형이나 선은 어떻게 그릴 수 있을까요?
바로 경로(path)를 지정하는 방식으로 표현하게 됩니다.

path는 출발점에서 시작하여 여러 중간점을 지나 도착점까지 이어지는 경로입니다.
한 붓 그리기를 예로 들면 이해가 쉬울 것 같습니다.

설명보다는 예제가 이해하기 쉬우니 아래 함수들부터 살펴보겠습니다.

beginPath()
: 새로운 경로를 만듭니다. 경로가 생성됬다면, 이후 그리기 명령들은 경로를 구성하고 만드는데 사용하게 됩니다.
moveTo(x,y)
: 특정 좌표로 이동합니다.
lineTo(x,y)
: 현재 지점에서 (x,y)좌표까지 선으로 연결합니다.
arc(x,y,radius,startAngle, endAngle, anticlockwise)
: (x,y) 위치에 원점을 두면서, 반지금 radius을 가지고, startAngle부터 endAngle까지 주어진 방향(anti-clockwise, 반시계방향)으로 호(arc)를 그립니다. 원 같은 곡선을 표현할 수 있습니다. 기본 방향은 시계방향.
arcTo(x1,y1,x2,y2,radius)
: 주어진 제어점들과 반지름으로 호를 그리고, 이전 점과 직선으로 연결합니다.
closePath()
: 현재 하위 경로의 시작 부분과 연결된 직선을 추가합니다. (필수 아님)
stroke()
: 윤곽선을 이용하여 도형을 그립니다.
fill()
: 경로의 내부를 채워서 내부가 채워진 도형을 그립니다.

함수를 봐도 알듯 말듯합니다. 이름은 쉬운데 어떻게 그림이 그려지는건지 과정이 그려지지 않습니다.

지금부터는 그림을 그리는 과정을 따라 설명하겠습니다.

  1. canvas를 선언하고 contexts를 가져옵니다.
  2. beginPath는 지금부터 그리기를 시작하겠다는 선언입니다. 아직은 path가 없습니다.
  3. 초기화 직후에는 시작 위치를 지정하는 것이 좋습니다. moveTo(x,y) 함수로 시작점을 설정합니다. 여기서부터 path가 시작됩니다.

    참고) beginPath() 직후 또는 캔버스를 새로 생성한 직후 첫 경로 생성 명령은 moveTo()로 취급됩니다.

  4. lineTo(x,y) 함수를 여러번 사용하여 표현하고자 하는 도형의 선을 그립니다. 현재 위치에서 (x,y)까지 펜으로 선을 그린다고 생각하면 됩니다. 그러면 펜이 (x,y)까지 이동하겠죠? path가 (x,y)까지 옮겨집니다. 하지만 아직 눈에 보이는 출력물은 없습니다.
  5. fill() 또는 stroke() 함수를 이용하여 출력합니다. 방금까지 지나온 path를 따라 fill 또는 stroke이 수행됩니다.

이러한 방식으로 그림을 그릴 수 있고, 곡선은 arc 등의 함수를 이용하여 표현할 수 있습니다.

아래는 삼각형을 그리는 예제입니다.

function drawTriangle() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.beginPath(); // 시작 선언
ctx.moveTo(75, 50); // 시작점 좌표 (75, 50)
ctx.lineTo(100, 75); // 시작점부터 (100, 75)까지 직선
ctx.lineTo(100, 25); // (100, 75)부터 (100, 25)까지 직선
ctx.fill(); // 내부 채우기. 이때 끝점과 시작점이 이어집니다.
}

결과물은 아래처럼 출력됩니다.

더 복잡한 곡선, 베지어(Bezier) 곡선과 이차(Quadratic) 곡선

이보다 더 복잡한 도형을 그리기 원한다면 아래 함수를 이용할 수 있습니다.

quadraticCurveTo(cp1x, cp1y, x, y)
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

관련 내용은 참고자료 두 번째 링크를 확인해주세요.

색(color) 변경하기

위 예제에서 그린 삼각형은 검정색이었습니다. 그렇다면 색깔은 어떻게 바꿀 수 있을까요?

바로 strokeStyle()fillStroke() 함수를 사용하면 됩니다.

참고자료의 예제를 통해 살펴보겠습니다.

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8"/>
  <script type="application/javascript">
    function draw() {
      var canvas = document.getElementById("canvas");
      if (canvas.getContext) {
        var ctx = canvas.getContext("2d");

        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 50, 50);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 50, 50);
      }
    }
  </script>
 </head>
 <body onload="draw();">
   <canvas id="canvas" width="150" height="150"></canvas>
 </body>
</html>

rgb 색상 또는 투명도 alpha 까지 추가된 rgba 함수를 통해 색을 지정하면, 다시 다른 색이 지정될 때까지 해당 색으로 fill 또는 stroke을 수행하게 됩니다.

결과물:

마치며

이번 포스트에서는 canvas 태그를 통해 기본적인 선과 도형을 그리는 방법에 대해 알아보았습니다.
단순한 내용이지만 점과 선, 면을 조합한다면 꽤 멋진 그림도 표현할 수 있을 것 같습니다.

다음 포스트는 canvas위에 마우스로 그림을 그리는 스크립트로 이어집니다.

참고자료

  1. 캔버스(Canvas) 기본 사용법:
    https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Basic_usage

  2. 캔버스(canvas)를 이용한 도형 그리기:
    https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes

  3. 스타일과 색 적용하기:
    https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors

0개의 댓글