1-1-2.캔버스 예제

캔버스는 <canvas> 태그로 출력 영역을 지정하며 자바스크립트의 그리기 메서드를 호출하여 캔버스에 원하는 그림을 그린다. 캔버스를 사용하는 가장 간단한 형식은 다음과 같다.

 

canvastest.html

<!DOCTYPE html>

<head>

     <meta charset="utf-8">

     <title>canvastest</title>

</head>

<body>

     <p>캔버스에 직접 그린다.</p>

     <canvas id="canvas" width="400" height="200">

     </canvas>

     <script>

         window.onload = function() {

              var canvas = document.getElementById("canvas");

              if (canvas == null || canvas.getContext == null) return;

              var ctx = canvas.getContext("2d");

              ctx.strokeRect(10,10,100,100);

         }

     </script>

</body>

</html>

 

<p> 태그로 문단을 배치하고 <canvas> 태그로 캔버스를 정의한다. <canvas>도 다른 태그와 마찬가지 자격을 가진다는 것을 보이기 위해 문단과 함께 배치했다. 캔버스 아래쪽에도 물론 다른 태그를 얼마든지 배치할 수 있으며 여러 개의 캔버스를 배치할 수도 있다. 캔버스의 주요 속성은 다음 세 개가 있다.

 

id : 캔버스는 그리기 영역만 정의할 뿐이며 그리기 동작은 코드에서 처리한다. 스크립트에서 캔버스를 참조해야 하므로 반드시 id 지정해야 한다. 여러 개의 캔버스를 배치할 경우 각각 다른 id 주어야 한다.

width, height : 캔버스의 크기를 픽셀 단위로 지정하며 실행중에 크기를 변경하는 것도 가능하다. 디폴트 크기는 300 * 150으로 좁게 설정되어 있는데 그리고자 하는 내용을 충분히 표현할만한 크기로 변경하면 된다.

 

3개의 속성은 거의 필수적으로 지정해야 한다. 물론 이 외에도 class, title, hidden 같은 전역 속성도 지정할 수 있다. 캔버스를 배치한 후 자바스크립트에서 그리기 메서드를 호출하여 그래픽을 출력한다. 페이지가 완전히 로드된 후에 그려야 하므로 window onload 이벤트에 그리기 코드를 작성하는 것이 좋다. 그림만 그릴 때는 아무 때나 그려도 상관없지만 이미지나 사운드같은 부속 파일이 있는 경우는 부속 파일까지 로드되어야 제대로 동작할 수 있다. 이 시점이 바로 onload이다.

getElementById 메서드로 캔버스 객체를 먼저 찾고 캔버스의 getContext 메서드로 그리기 컨텍스트를 구한다. 아직까지는 에러 처리가 필요하다. canvas 태그가 문서에 없으면 그릴 영역이 없다는 뜻이고 컨텍스트를 찾는 메서드가 없다면 브라우저가 캔버스를 지원하지 않는다는 뜻이다. 이 경우는 더 이상 그리기를 하지 말고 바로 리턴해야 한다.

컨텍스트는 캔버스의 그리기 영역이면서 그리기 메서드를 가지는 객체이다. getContext 메서드의 인수로 원하는 컨텍스트의 종류를 전달한다. 현재는 2d 그리기만 가능하나 OpenGL ES를 개량한 WebGL이 개발되고 있는 중이므로 조만간 3d 그리기로 확장될 예정이다. getContext의 인수로 전달되는 컨텍스트 종류는 문자열이므로 반드시 따옴표로 감싸 "2d"라고 적어야 하며 대문자를 인정하지 않으므로 "2D"라고 적어서는 안된다.

 

canvas.getContext("2d")            // 맞음

canvas.getContext("2D")           // 틀림

canvas.getContext(2d)              // 틀림  

 

getContext("2d") 호출로 CanvasRenderingContext2D 타입의 객체가 리턴되는데 이 객체가 바로 그리기 메서드와 속성을 가지는 컨텍스트이다. 컨텍스트를 ctx 변수에 대입하고 이후부터 ctx의 메서드로 그리기를 수행한다. 예제에서는 strokeRect 메서드로 사각형을 그렸다. 캔버스 안쪽에 회색 사각형이 출력된다.

 

위 예제는 캔버스를 사용하는 기본적인 절차를 잘 보여 준다. 문서의 적당한 위치에 캔버스 태그를 배치하고 문서 로드가 완료되는 onload 이벤트에 그리기 코드를 작성한다. 캔버스 객체를 찾고 캔버스로부터 컨텍스트를 구한 후 컨텍스트의 그리기 관련 메서드를 호출하는 식이다. 이 코드는 거의 정형화되어 있으며 이후 달라지는 부분은 컨텍스트에서 호출하는 메서드이다. 어떤 메서드를 호출할 것인가에 따라 출력이 달라진다.

캔버스를 찾고 컨텍스트를 구하고 에러 처리하는 과정은 항상 반복되는 과정이며 호출하는 그리기 메서드만 달라질 뿐이다. 실습 편의와 에러 처리, 그리고 명확한 결과 확인을 위해 예제를 다음과 같이 재작성하였다.

 

canvasexample.html

<!DOCTYPE html>

<head>

     <meta charset="utf-8">

     <title>canvasexample</title>

     <style>

         canvas {border:5px solid magenta;}

     </style>

</head>

<body>

     <canvas id="canvas" width="400" height="200">

         이 브라우저는 캔버스를 지원하지 않습니다.

     </canvas>

     <script>

         var canvas;

         var ctx;

         window.onload = function() {

              canvas = document.getElementById("canvas");

              if (canvas == null || canvas.getContext == null) return;

              ctx = canvas.getContext("2d");

              draw();

         }

        

         function draw() {

              ctx.strokeRect(10,10,100,100);

         }

     </script>

</body>

</html>

 

캔버스 자체는 그리기 영역일 뿐이므로 내용물이 없다. 아무것도 그리지 않으면 빈 사각형이라 존재가 보이지 않는다. 그래서 스타일을 지정하여 5픽셀의 두꺼운 분홍색 경계선을 그려 넣었다. 좀 유치하지만 코드에 의한 그래픽 출력과 구분하기 위해 잘 안쓰는 색으로 지정했다. 실행 결과는 다음과 같다. 분홍색 경계가 없으면 어디가 캔버스 영역인지 구분되지 않는다. 물론 실제 프로젝트에서는 경계선이 없어도 무방하다.

<canvas> 태그의 안쪽에는 캔버스를 지원하지 못하는 브라우저를 위해 대체물을 넣는다. 캔버스 크기와 동일한 이미지가 가장 이상적이다. 크기가 동일해야 레이아웃이 유지된다. 이왕이면 이미지의 alt 속성에 설명을 작성하여 시각 장애인도 배려하는 것이 좋다. 예제에서는 간단하게 안내 문자열만 넣었다.

캔버스와 컨텍스트 객체 canvas, ctx를 코드의 어디에서나 참조할 수 있도록 전역 변수로 선언했다. 이 두 객체는 캔버스를 프로그래밍하려면 늘 필요하므로 전역으로 선언하는 것이 편리하다. 사실 canvas 객체는 ctx canvas 속성으로도 구할 수 있으므로 굳이 전역이 아니어도 상관없지만 한 단계 더 거치는 것이 귀찮아 따로 선언해 두었다.

onload의 이벤트 핸들러에서 하는 일은 거의 일정하므로 더 이상 살펴볼 필요가 없다. 그래서 그리기와 관련된 코드만 draw 메서드로 분리했다. draw는 전역으로 선언된 ctx의 메서드를 호출하여 그림을 출력하고 그리기 속성을 변경한다. 이후 실습에서는 draw 메서드 안쪽만 보이기로 한다. 지면 절약뿐만 아니라 독자들이 살펴봐야 할 코드를 최소하하여 집중하기 쉽도록 하기 위해서이다.

실행결과도 분홍색 사각형 안쪽만 달라지므로 굳이 브라우저 전체를 다 보일 필요가 없으며 이 사각형 안쪽만 지면에 캡처해서 보이도록 한다. 물론 이 소스는 실습 편의를 위해 작성한 것 뿐이므로 실제 프로젝트의 형태는 다앙할 것이다. 이 구조와 달라지는 예제만 전체 소스를 보일 것이다.