HTML5 캔버스 변환 행렬이란?
HTML5 캔버스(Canvas)는 변환 행렬(transformation matrix)을 직접 수정할 수 있는 메서드를 제공합니다. 변환 행렬은 처음에 반드시 항등 변환(identity transform) 상태여야 하며, 이후 다양한 변환 메서드를 사용해 자유롭게 조정할 수 있습니다.
변환 행렬을 활용하면 도형의 회전, 확대·축소, 기울이기(skew), 이동 등을 하나의 행렬 연산으로 처리할 수 있어 복잡한 그래픽 작업을 효율적으로 구현할 수 있습니다.
transform() 메서드
transform(m11, m12, m21, m22, dx, dy) 메서드는 현재 변환 행렬에 아래와 같은 행렬을 곱합니다.
m11 m21 dx m12 m22 dy 0 0 1
즉, 기존의 변환 상태를 유지한 채 새로운 변환이 누적되어 적용됩니다. 여러 번 호출하면 그때마다 변환이 계속 곱해지므로, 반복문과 함께 사용하면 패턴이나 회전 도형을 손쉽게 그릴 수 있습니다.
setTransform() 메서드
setTransform(m11, m12, m21, m22, dx, dy) 메서드는 먼저 현재 변환을 항등 행렬로 초기화한 뒤, 동일한 인수로 transform(m11, m12, m21, m22, dx, dy) 메서드를 호출하는 것과 같은 동작을 수행합니다.
transform()과 달리 누적된 변환을 모두 무시하고 새로 설정하기 때문에, 특정 좌표계로 한 번에 전환하고 싶을 때 유용합니다.
예제 코드
아래 예제는 transform()으로 회전 변환을 반복 적용해 색상이 점점 밝아지는 사각형들을 그리고, setTransform()으로 좌표계를 재설정하여 반투명 파란 사각형을 추가로 그립니다.
<!DOCTYPE HTML>
<html>
<head>
<script>
function drawShape(){
// DOM으로 캔버스 요소 가져오기
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('이 데모를 보려면 Safari 또는 Firefox 1.5+가 필요합니다.');
}
}
</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도 회전에 필요한 삼각함수 값을 구합니다.
2. 원점 이동: translate(200, 200)으로 캔버스 중앙으로 좌표 원점을 옮깁니다.
3. 반복 회전 그리기: for 반복문 안에서 fillRect()로 사각형을 그린 후, transform(cos, sin, -sin, cos, 0, 0)을 호출해 매번 30도씩 누적 회전시킵니다. 색상은 rgb(c, c, c) 형태로 명도가 단계적으로 밝아지므로, 소용돌이처럼 퍼지는 사각형 패턴이 완성됩니다.
4. 변환 초기화 후 새 도형 그리기: setTransform(-1, 0, 0, 1, 200, 200)으로 변환을 초기화하면서 x축을 반전(수평 미러링)하고 원점을 (200, 200)으로 지정한 뒤, 반투명 파란색 사각형을 그려 마무리합니다.
이처럼 transform()은 변환을 누적 적용할 때, setTransform()은 변환을 한 번에 재설정할 때 사용한다는 차이를 기억하면 됩니다.