[HTML/canvas] 변형 (transformations)

mdn의 캔버스 튜토리얼 따라하기
참고 : 캔버스 튜토리얼



function drawTrans() {
    var ctx = document.getElementById("transCanvas").getContext("2d");

    // save(상태저장) & restore(가장 최근 canvas 상태 복원)
    /*
    * 이게 개념이 헷갈릴 수 있는데 
    * 저장공간 스택에 save로 상태를 push하고
    * restore로 pop해서 복원하는 것
    * (restore를 실행취소로 잘못 생각했었음)
    */
    ctx.fillRect(0,0,150,150);
    ctx.save(); // 기본 상태 저장(push1)

    // 설정 변경
    ctx.fillStyle = "#09F";
    ctx.fillRect(15,15,60,120);
    ctx.fillStyle = "#90F";
    ctx.fillRect(75,15,60,120);

    ctx.save(); // 현재 상태 저장(push2)
    ctx.fillStyle = "#FFF";
    ctx.globalAlpha = 0.5;
    ctx.fillRect(30,30,90,90);

    ctx.restore(); // 이전 상태 복원(push2 상태를 pop)
    ctx.fillRect(45,45,60,60); // 복원된 설정으로 사각형 그리기

    ctx.restore();// (push1 상태를 pop) 저장공간 스택을 모두 pop 했으므로 이후에 restore를 여러번해도 변경x
    ctx.fillRect(60,60,30,30);

    ctx.translate(160,0);
    ctx.save();

    // translate(canvas 원점 이동)
    for(var i=0; i<3; i++) {
       for(var j=0; j<3; j++) {
           ctx.save();
           ctx.fillStyle = "rgb(" + 51*i + ", " + (255-51*i) + ", 255)";
           ctx.translate(10+j*50, 10+i*50);
           ctx.fillRect(0,0,25,25);
           ctx.restore();
       }
    }

    ctx.translate(200,0);
    ctx.save();

    // rotate(캔버스 회전(원점을 기준으로 회전))
    ctx.fillStyle = "#0095DD";
    ctx.fillRect(0,0,100,100);

    // 각도의 단위는 도(degree)가 아닌 라디안(radian)
    // 변환 시 radians = (Math.PI/180)*degrees(각도)
    ctx.rotate((Math.PI / 180) * 25);

    // 회색 사각형
    ctx.fillStyle = "rgba(77,78,83,0.5)";
    ctx.fillRect(0,0,100,100);
    ctx.restore();

    // 우측 사각형, 사각형 중심에서 회전하기
    // 파란 사각형 그리기
    ctx.fillStyle = "#0095DD";
    ctx.fillRect(150,30,100,100);

    ctx.translate(200, 80); // 사각형 중심으로 이동
    ctx.rotate((Math.PI / 180)*25);
    ctx.translate(-200, -80);

    // 회색 사각형 그리기
    ctx.fillStyle = "rgba(77,78,83,0.5)";
    ctx.fillRect(150, 30, 100, 100);
}




    var ctx = document.getElementById("transCanvas2").getContext("2d");

    // scale
    // 확대, 축소 비율을 적용한 사각형 그리기
    // 동일한 크기로 사각형을 그렸을때 스케일에 따라 다르게 출력됨
    ctx.fillStyle = "black";
    ctx.fillRect(5,5,20,20); // 원본 사각형
    ctx.save();

    ctx.scale(2,2);
    ctx.fillStyle = "red";
    ctx.fillRect(15,2,20,20); // 확대 사각형

    ctx.scale(0.3,0.3);
    ctx.fillStyle = "blue";
    ctx.fillRect(125,10,20,20); // 축소 사각형

    ctx.restore();
    ctx.translate(220,5);
    ctx.save();

    // 수평으로 대치하기
    ctx.font = "48px serif";
    ctx.textBaseline = "alphabetic";
    ctx.fillStyle = "blue";
    ctx.fillText("snow", 0, 23);
    ctx.scale(-1, 1);
    ctx.fillStyle = "red";
    ctx.fillText("snow", 0, 23);
    ctx.scale(1, -1);
    ctx.fillStyle = "red";
    ctx.fillText("snow", 0, -25);
    ctx.scale(-1, 1);
    ctx.fillStyle = "blue";
    ctx.fillText("snow", 0, -25);

    ctx.restore();
    ctx.translate(130,0);
    ctx.fillRect(0,0,20,20); // 원본 사각형

    // transform & setTransform
    // 1. 직사각형 회전
    // 30도 각도에 대한 sin, cos 계산
    var sin = Math.sin(Math.PI / 6);
    var cos = Math.cos(Math.PI / 6);

    ctx.translate(100,100); // 원점이동
    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,10);

        // ctx.transform(수평 확대/축소, 수평 비스듬히 기울이기, 수직 비스듬히 기울이기, 수직 확대/축소, 수평 이동, 수직 이동)
        ctx.transform(cos, sin, -sin, cos, 0, 0);
    }

    // resetTransform() == ctx.setTransform(1, 0, 0, 1, 0, 0)
    ctx.setTransform(1, 0, 0, 1, 350, 90);
    ctx.fillStyle = "rgba(255,128,255,0.5)";
    ctx.fillRect(0,0,100,100);