Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

HTML5 캔버스의 변환 행렬이란 무엇일까?

HTML5 캔버스는 변환 행렬(transformation matrix)을 직접 수정할 수 있는 다양한 메서드를 제공합니다. 캔버스가 처음 생성될 때 변환 행렬은 반드시 항등 변환(identity transform) 상태여야 하며, 이후 여러 변환 메서드를 통해 자유롭게 조정할 수 있습니다.

주요 변환 메서드 정리

변환 행렬을 활용하면 도형을 이동, 회전, 확대·축소하는 등 복잡한 그래픽 효과를 손쉽게 구현할 수 있습니다. 대표적인 변환 메서드는 다음과 같습니다.

  • translate(x, y) – 캔버스의 원점을 지정한 좌표만큼 이동합니다.
  • rotate(angle) – 캔버스를 라디안 단위의 각도만큼 회전합니다.
  • scale(x, y) – 가로·세로 방향의 크기를 확대하거나 축소합니다.
  • transform(a, b, c, d, e, f) – 현재 변환 행렬에 새로운 행렬을 곱하여 변환을 누적 적용합니다.
  • setTransform(a, b, c, d, e, f) – 기존 행렬을 무시하고 지정한 행렬로 완전히 재설정합니다.

실습 예제

다음은 캔버스 변환 행렬을 활용한 대표적인 예제입니다. 사각형을 반복해서 그리면서 매번 30도씩 회전시켜 바람개비 같은 돌무늬 패턴을 만들고, 마지막에는 setTransform()으로 행렬을 초기화한 뒤 반투명한 파란색 사각형을 추가로 그립니다.

<!DOCTYPE HTML>
<html>
   <head>
      <script>
         function drawShape(){

            // DOM을 사용하여 canvas 요소 가져오기
            var canvas = document.getElementById('mycanvas');

            // 캔버스를 지원하지 않는 경우 실행하지 않음
            if (canvas.getContext){
               // getContext로 2D 드로잉 컨텍스트 사용
               var ctx = canvas.getContext('2d');
               var sin = Math.sin(Math.PI/6);
               var cos = Math.cos(Math.PI/6);
               ctx.translate(200, 200);
               var c = 0;

               for (var i=0; i <= 12; i++) {
                  c = Math.floor(255 / 12 * i);
                  ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
                  ctx.fillRect(0, 0, 100, 100);
                  ctx.transform(cos, sin, -sin, cos, 0, 0);
               }
               ctx.setTransform(-1, 0, 0, 1, 200, 200);
               ctx.fillStyle = "rgba(100, 100, 255, 0.5)";
               ctx.fillRect(50, 50, 100, 100);
            }
            else {
               alert('You need Safari or Firefox 1.5+ to see this demo.');
            }
         }
      </script>
   </head>
   <body onload = "drawShape();">
      <canvas id = "mycanvas" width = "400" height = "400"></canvas>
   </body>
</html>

코드 동작 원리 살펴보기

  1. 회전 각도 계산 : Math.sin(Math.PI/6)Math.cos(Math.PI/6)로 30도(π/6 라디안) 회전에 필요한 삼각 함수 값을 미리 구해 둡니다.
  2. 원점 이동 : ctx.translate(200, 200)으로 원점을 캔버스 중앙(400×400 기준)으로 옮겨 회전의 기준점을 중앙에 맞춥니다.
  3. 반복 그리기와 누적 회전 : for 루프 안에서 명도가 점점 어두워지는 회색조 사각형(fillRect)을 그린 뒤, ctx.transform(cos, sin, -sin, cos, 0, 0)으로 매번 30도씩 회전 변환을 누적 적용합니다. 결과적으로 12개의 사각형이 겹쳐진 회전 패턴이 완성됩니다.
  4. 행렬 재설정 후 추가 도형 : ctx.setTransform(-1, 0, 0, 1, 200, 200)으로 변환 행렬을 수평 반전과 평행 이동이 적용된 새로운 상태로 초기화하고, 반투명 파란색(rgba(100, 100, 255, 0.5)) 사각형을 하나 더 그려 마무리합니다.

이처럼 transform()은 기존 변환 위에 새 변환을 계속 쌓아가는 데 유용하고, setTransform()은 지금까지의 모든 변환을 한 번에 덮어써야 할 때 사용합니다. 두 메서드의 차이를 이해하면 캔버스에서 훨씬 정교하고 자유로운 그래픽 연출이 가능합니다.