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

HTML5 캔버스 translate() 메서드로 원점 이동하기

translate() 메서드란?

HTML5 캔버스에서는 translate(x, y) 메서드를 사용해 캔버스와 그 원점(origin)을 그리드상의 다른 위치로 이동할 수 있습니다. 변환(transformation) 기능 중 하나인 translate()는 도형을 반복해서 그리거나 복잡한 좌표 계산 없이 패턴을 만들어야 할 때 특히 유용합니다.

각 매개변수의 의미는 다음과 같습니다.

  • x : 캔버스를 좌측(음수) 또는 우측(양수)으로 이동할 거리
  • y : 캔버스를 위쪽(음수) 또는 아래쪽(양수)으로 이동할 거리

translate()는 현재 변환 행렬에 이동 값을 더하는 방식으로 동작하기 때문에 여러 번 호출하면 이동이 누적됩니다. 따라서 save()restore() 메서드를 함께 사용해 변환 상태를 저장했다가 원래대로 되돌리는 패턴이 실무에서 널리 활용됩니다.

예제

다음 예제는 translate()와 스피로그래프(spirograph) 곡선 그리기 함수를 조합하여 3×3 격자 형태의 패턴을 캔버스에 출력합니다.

<!DOCTYPE HTML>
<html>
   <head>
      <style>
         #test {
            width:100px;
            height:100px;
            margin:0px auto;
         }
      </style>
     
      <script>
         function drawShape(){
            // get the canvas element using the DOM
            var canvas = document.getElementById('mycanvas');
            
            // Make sure we don't execute when canvas isn't supported
            if (canvas.getContext){
               // use getContext to use the canvas for drawing
               var ctx = canvas.getContext('2d');
               ctx.fillRect(0,0,300,300);
               for (i = 0; i < 3; i++) {
                  for (j = 0; j < 3; j++) {
                     ctx.save();
                     ctx.strokeStyle = "#FF0066";
                     ctx.translate(50+j*100,50+i*100);
                     drawSpirograph(ctx,10*(j+3)/(j+2),-2*(i+3)/(i+1),10);
                     ctx.restore();
                  }
               }
            } else {
              alert('You need Safari or Firefox 1.5+ to see this demo.');
            }
         }
         
         function drawSpirograph(ctx,R,r,O){
            var x1 = R-O;
            var y1 = 0;
            var i = 1;
            ctx.beginPath();
            ctx.moveTo(x1,y1);
            do {
            if (i>20000) break;
            var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72));
            var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72));
            ctx.lineTo(x2,y2);
            x1 = x2;
            y1 = y2;
            i++;
            } while (x2 != R-O && y2 != 0 );
            ctx.stroke();
         }
    </script>
   </head>

   <body id = "test" onload = "drawShape();">
      <canvas id = "mycanvas" width = "400" height = "400"></canvas>
   </body>
</html>

코드 설명

drawShape() 함수는 먼저 DOM에서 캔버스 요소를 가져온 뒤, getContext('2d')로 2D 드로잉 컨텍스트를 얻습니다. 이후 300×300 크기의 사각형으로 배경을 채우고, 이중 for 루프를 실행하며 각 셀마다 다음 순서로 작업을 수행합니다.

  1. save()로 현재 캔버스 상태를 저장
  2. strokeStyle을 분홍색(#FF0066)으로 지정
  3. translate(50+j*100, 50+i*100)으로 원점을 격자 위치에 맞게 이동
  4. drawSpirograph()를 호출해 곡선을 그린 후 restore()로 상태 복원

drawSpirograph() 함수는 cos, sin 같은 삼각함수를 이용해 하이포트로이드(hypotrochoid) 곡선의 좌표를 계산합니다. 매개변수 R, r, O 값에 따라 곡선의 모양이 달라지며, i > 20000 조건으로 반복 횟수를 제한해 무한 루프를 방지합니다.

이 예제는 Safari나 Firefox 1.5 이상처럼 canvas 요소를 지원하는 브라우저에서 정상적으로 동작하며, 미지원 브라우저에서는 안내 알림 창이 표시되도록 처리되어 있습니다.