티스토리 뷰

[원글 - 2012년 이글루스]


Canvas2D를 이용해야하는 작업이 생겨서 이것저것 만져보다가


나중에 다시 볼 때 가장 햇갈려할 것 같은 Transform부분을 정리한다

HTML5의 Canvas2D에는 다음과 같은 변환(Transform) 함수들이 있다

scale( x, y )
rotate( angle )
translate( x, y )
transform( a, b, c, d, e, f )
setTransform( a, b, c, d, e, f )

Canvas2D의 변환은 여타 3D API에서 제공하는 변환처럼 행렬로 처리된다

동차 좌표계를 포함 Canvas2D에 사용되는 행렬은 3 by 3 행렬이 된다.

변환 할 좌표를 x, y 라 하고, 최종 변환 된 좌표를 x', y' 이라고 했을 때,

변환 공식은 다음과 같다.




위쪽은 OpenGL을 많이 다뤄본 사람들에게 익숙한 행렬 곱 표현 방법이고

아래쪽은 DirectX를 많이 다뤄본 사람들에게 익숙한 행렬 곱 표현 방법이다

어느쪽이든 결과는 같다

눈치 빠른 사람은 눈치 챘으리라고 생각하지만

위 그림의 행렬에서 a, b, c, d, e, f는  위에서 설명한 함수 중

transform( a, b, c, d, e, f )
setTransform( a, b, c, d, e, f )

두 함수의 패러미터 a, b, c, d, e, f 이다

사실 상 변환에는 행렬에서 저 6개의 값만 사용된다.

많은 사이트 들이 

패러미터를 다음과 같이 정의한다

a :  scale-x
b :  skew-x
c :  skew-y
d :  scale-y
e :  translate-x
f  :  translate-y

틀린 말은 아니지만

이동 후 확대, 회전 후 이동 후 확대 등으 변환을 적용하려면 아무래도 위의 행렬 식으로 기억하는게 좋다

HTML5 에서의 변환 함수는 OpenGL과 비슷한 방식으로 동작한다

기본적으로 변환 행렬이 내부에 존재하고

setTransform()을 제외한 나머지 4개의 함수들이 호출될 때마다 행렬이 곱해진다

따라서 함수의 호출 순서는 변환에 영향을 준다

가령, 이동 후에 회전을 하고 싶다고 한다면

rotate() 함수를 먼저 호출하고 그 이후에 translate() 함수를 호출한다

가장 마지막에 호출된 함수부터 적용된다고 보면 된다

이동 후에 회전을 행렬 곱으로 나타내면 아래와 같을 것이다




함수 호출은 위 그림에서 첫번째 식의 형태를 취한다고 생각하면 된다

                                ┌ x ┐
함수를 호출할 때마다 |   y  |  앞에 행렬이 붙는다고 생각하면 된다
                                └ 1  ┘

순서 역시 [ x y 1 ] 벡터에 가까운 행렬부터 곱한다고 생각하면 된다

아래의 식이 어떻게 보면 더 직관적으로 보이긴 하지만

일단 표준 변환은 위의 식의 방식을 따른다는 점을 알아두자


마지막으로 setTransform() 함수는 행렬을 새로 곱하는게 아니라

변환 행렬을 패러미터 값으로 set 해버린다

따라서 변환 행렬을 초기화 하고 싶은 경우는 다음과 같이 호출하여 단위 행렬로 만들 수 있다

setTransform( 1, 0, 0, 1, 0, 0 );

왜 위와 같은지는 각 패러미터 자리를 제일 처음 식에 대입해 보라

또는 미리 변환 행렬을 계산해 놓고 때에 따라 바꿔서 적용해 볼 수도 있을 것이다


p.s. Transform의 경우 그려지는 객체에 적용되기 보다는 Canvas 자체에 적용된다는 사실을 알아두자

이게 어떤 결과를 가져다 주는지는 Path를 적용해 보면 알 수 있다

이부분은 따로 글을 작성하도록 하겠다


댓글
최근에 올라온 글
Total
Today
Yesterday
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31