[HTML5 Canvas] 06 캔버스 트랜스폼

9rganizedChaos·2021년 6월 11일
0

HTML5_Canvas

목록 보기
6/6
post-thumbnail

✹ 해당 포스팅은 Youtube에 업로드된 1분코딩님의 <HTML5 Canvas 캔버스 라이브 강좌>의 필기입니다.
이 곳을 클릭하시면 유튜브에서 직접 강좌를 들으실 수 있습니다.
대부분의 샘플 코드는 해당 강좌에서 제공되는 코드임을 밝힙니다.

캔버스에서 역시 CSS의 transform 속성과 같이 이미지나 영상의 크기, 위치를 바꿀 수 있으며, 도형이나 이미지를 찌그러뜨리거나 회전을 할 수도 있다. 공식문서를 참고하면 가장 먼저 transform API와 관련해 등장하는 것이 바로 상태의 저장과 복원이다.

State의 저장과 복원

공식문서에서는 트랜스폼을 다루기 위해 저장과 복원 메소드를 꼭 알아야 한다고 이야기한다.
물론 여기서 다루는 save와 restore는 모두 컨텍스트의 메소드들이다.

save 메소드를 호출하면 drawing의 상태가 스택에 저장되며, restore 메소드를 호출하면 저장된 상태를 스택에서 꺼내온다.

drawing의 상태에 해당하는 것은 공식문서에서 알아볼 수 있다.
대표적인 예시는 fillStyle, lineWidth, shadowColor, direction 등

앞서 캔버스의 state를 save하면 이것이 스택에 저장된다고 하였다.
때문에 공식문서에 아래와 같은 예시가 등장한다.

// save와 restore는 중첩해서 사용이 가능하다!

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

  ctx.fillRect(0, 0, 150, 150);   // 기본 설정으로 사각형을 그리기
  ctx.save();                  // 기본 상태를 저장하기

  ctx.fillStyle = '#09F';      // 설정 변경하기
  ctx.fillRect(15, 15, 120, 120); // 새로운 설정으로 사각형 그리기

  ctx.save();                  // 현재 상태 저장하기
  ctx.fillStyle = '#FFF';      // 설정 변경하기
  ctx.globalAlpha = 0.5;
  ctx.fillRect(30, 30, 90, 90);   // 새로운 설정으로 사각형 그리기

  ctx.restore();               // 이전 상태 복원하기 (가장 최근에 저장된 걸 먼저 꺼내옴)
  ctx.fillRect(45, 45, 60, 60);   // 복원된 설정(#FFF)으로 사각형 그리기

  ctx.restore();               // 초기 상태를 복원하기 (처음에 저장한 건 나중에 꺼내옴)
  ctx.fillRect(60, 60, 30, 30);   // 복원된 설정(#09F)으로 사각형 그리기
}

본격적인 트랜스폼 적용!

캔버스는 고수준의 API가 아니다! 무조건 왼쪽 위가 기준이 된다.

      const canvas = document.querySelector('.canvas');
      const context = canvas.getContext('2d');
      let scaleValue = 1;
      let rotationValue = 0;

      function toRadian(d) {
        return d * Math.PI/180;
      }

      function draw() {
        // context.clearRect(0, 0, canvas.width, canvas.height);
        context.save();
        context.setTransform(1,0,0,1,0,0);
        // 변환전에 디폴트 설정해주는 메소드! 곱해주는 값?을 단위행렬로 설정한다!
        // 더 복잡한 트랜스폼을 시도하다보면 꼭 이용해야 한다.
        // context.resetTransform();
        context.translate(350, 350);
        // ctx.translate(x, y) x, y축으로 이동하는 메소드
        // 기준점을 다시 잡아주는 과정
        context.scale(scaleValue, scaleValue);
        context.rotate(toRadian(rotationValue));
        context.strokeRect(-50, -50, 100, 100);
        // -50을 해주는 이유는 그렇게 해야 중앙이 기준점이 되어서 회전하기 때문
        // -50자리에 0을 기입해주면 좌측 상단 꼭짓점을 기준으로 회전한다!

        // context.setTransform(1,0,0,1,0,0);
        // context.fillRect(10, 10, 30, 30);
        context.restore();

        context.fillRect(10, 10, 30, 30);
        // ☝🏻 ☝🏻 ☝🏻 ☝🏻 ☝🏻 ☝🏻 ☝🏻 

        scaleValue += 0.05;
        rotationValue += 1;

        requestAnimationFrame(draw);
      }

      draw();

save와 restore를 썼을 때와 그렇지 않았을 때의 차이!

코드 내에서 <☝🏻> 표시 한 부분의 사각형의 위치가 달라진다!
save를 가장 상단에서 설정해주면 translate(350, 350)이 적용안된 상태가 저장된다.
그리고 restore이후에 <☝🏻> 부분을 실행해주면 translate(350, 350)이 적용안된 상태로 네모가 그려진다.
save와 restore를 해주지 않으면, <☝🏻> 부분의 사각형이 translate(350, 350)가 적용된 상태로 그려진다.

save와 restore 저장했을 때!

적용하지 않았을 때!

profile
부정확한 정보나 잘못된 정보는 댓글로 알려주시면 빠르게 수정토록 하겠습니다, 감사합니다!

0개의 댓글