1. 소개
이 섹션은 규범적이지 않습니다.
CSS 시각적 포맷팅 모델은 각 요소가 배치되는 좌표계를 설명합니다. 이 좌표 공간에서 위치와 크기는 픽셀 단위로 표현된다고 볼 수 있으며, 원점에서 시작하여 오른쪽과 아래쪽으로 양의 값이 진행됩니다.
이 좌표 공간은 transform 속성으로 변경할 수 있습니다. transform을 사용하면 요소를 이동, 회전, 확대/축소할 수 있습니다.
1.1. 모듈 상호작용
이 모듈은 해당 속성이 적용된 요소의 시각적 렌더링에 영향을 주는 CSS 속성 집합을 정의합니다. 이러한 효과는 요소가 시각적 포맷팅 모델 [CSS2]에 따라 크기와 위치가 결정된 이후에 적용됩니다. 이 속성의 일부 값은 포함 블록을 생성하거나, 스태킹 컨텍스트를 생성할 수 있습니다.
Transform은 fixed 값이 지정된 background-attachment 속성을 가진 요소의 배경 렌더링에 영향을 줍니다. 이는 [CSS3BG]에서 정의되어 있습니다.
Transform은 getClientRects() 및 getBoundingClientRect()와 같은 Element 인터페이스 확장에서 반환되는 클라이언트 사각형에도 영향을 줍니다. 이는 [CSSOM-VIEW]에서 정의되어 있습니다.
Transform은 스크롤 가능한 오버플로우 영역의 계산에도 영향을 줍니다. 자세한 내용은 [CSS-OVERFLOW-3]를 참조하세요.
1.2. CSS 값
이 명세는 CSS 속성 정의 관례를 [CSS2]에서 따릅니다. 이 명세에서 정의되지 않은 값 타입은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈이 이러한 값 타입의 정의를 확장할 수 있습니다.
각 속성 정의에 명시된 속성 전용 값 외에도, 이 명세에서 정의된 모든 속성은 CSS-wide 키워드도 속성 값으로 사용할 수 있습니다. 가독성을 위해 이를 반복적으로 명시하지 않았습니다.
2. 용어 정의
이 명세에서 사용되는 용어는 본 섹션에서 정의된 의미를 갖습니다.
- 변환 가능한 요소
-
변환 가능한 요소란 다음 범주에 속하는 요소를 말합니다:
-
CSS 박스 모델에 의해 레이아웃이 결정되는 모든 요소(단, 교체되지 않은 인라인 박스, table-column 박스, table-column-group 박스는 제외) [CSS2],
-
모든 SVG 페인트 서버 요소, clipPath 요소, 그리고 SVG 렌더링 가능한 요소(단, 텍스트 콘텐츠 요소의 모든 자손은 제외) [SVG2].
-
- 변환된 요소
-
transform 속성의 계산값이 none이 아닌 요소.
- 사용자 좌표계
- 로컬 좌표계
-
일반적으로, 좌표계는 현재 캔버스에서 위치와 거리를 정의합니다. 현재 로컬 좌표계(사용자 좌표계)는 현재 활성화된 좌표계이며, 좌표와 길이가 어떻게 위치하고 계산되는지를 결정합니다. 현재 사용자 좌표계의 원점은 기준 박스(transform-box 속성으로 지정) 왼쪽 상단에 위치합니다. 백분율 값은 이 기준 박스의 크기를 기준으로 합니다. 한 단위는 1 CSS 픽셀과 같습니다.
- 변환 행렬
-
한 좌표계에서 다른 좌표계로의 수학적 매핑을 정의하는 행렬입니다. transform 및 transform-origin 속성 값에서 계산됩니다(아래 참조).
- 현재 변환 행렬 (CTM)
- 2D 행렬
-
3x2 변환 행렬 또는 다음 항목들이 0이고 m33, m44가 1인 4x4 행렬: m31, m32, m13, m23, m43, m14, m24, m34.
- 항등 변환 함수
-
변환 함수 중 항등 4x4 행렬과 동일한 함수(자세한 내용은 변환 함수의 수학적 설명 참조). 예시: translate(0), translateX(0), translateY(0), scale(1), scaleX(1), scaleY(1), rotate(0), skew(0, 0), skewX(0), skewY(0), matrix(1, 0, 0, 1, 0, 0).
- 포스트 곱셈
- 포스트 곱셈됨
-
용어 A를 용어 B로 포스트 곱셈한다는 것은 A · B와 같습니다.
- 프리 곱셈
- 프리 곱셈됨
-
용어 A를 용어 B로 프리 곱셈한다는 것은 B · A와 같습니다.
- 곱셈
-
용어 A를 용어 B로 곱셈한다는 것은 A · B와 같습니다.
3. 변환 렌더링 모델
이 섹션은 규범적입니다.
transform 속성에 none 이외의 값을 지정하면 해당 요소에 새로운 로컬 좌표계가 생성됩니다. 요소가 렌더링될 위치에서 이 로컬 좌표계로의 매핑은 요소의 변환 행렬로 주어집니다.
변환 행렬은 transform 및 transform-origin 속성에서 다음과 같이 계산됩니다:
-
항등 행렬로 시작합니다.
-
transform-origin의 계산된 X, Y만큼 이동합니다.
-
transform 속성의 변환 함수 각각을 왼쪽에서 오른쪽으로 곱합니다.
-
transform-origin의 계산된 X, Y의 부호 반대로 이동합니다.
요소에 transform 속성이 none이 아닌 값으로 지정되어 있습니다.
div {
transform-origin : 0 0 ;
transform : translate ( -10 px , -20 px ) scale ( 2 ) rotate ( 45 deg );
}
transform-origin 속성이 0 0으로 설정되어 있으므로 생략 가능합니다. 변환 행렬 TM은 <translate()>, <scale()>, <rotate()> <transform-function>를 포스트 곱셈하여 계산됩니다.
Transform은 변환 가능한 요소에 적용됩니다.
좌표 공간은 두 축(X축과 Y축)으로 이루어진 좌표계이며, X축은 오른쪽으로 수평 증가, Y축은 아래로 수직 증가합니다.
변환은 누적됩니다. 즉, 요소는 부모의 좌표계 내에 자신의 로컬 좌표계를 설정합니다.
요소의 로컬 좌표계에서 plocal (좌표쌍 xlocal, ylocal)을 부모 좌표계로 매핑하려면, 요소의 변환 행렬 TM에 plocal을 포스트 곱셈합니다. 결과는 부모 로컬 좌표계에서 좌표쌍 xparent, yparent를 갖는 pparent입니다.
사용자 관점에서 보면, 요소는 자신의 조상들의 모든 transform 속성뿐 아니라 자신에게 적용된 로컬 변환도 누적합니다. 이러한 변환의 누적은 요소의 현재 변환 행렬(CTM)을 정의합니다.
현재 변환 행렬은 뷰포트 좌표계에서 시작하여 요소의 변환 행렬까지 모든 변환 행렬을 포스트 곱셈하여 계산됩니다.
< svg xmlns = "http://www.w3.org/2000/svg" >
< g transform = "translate(-10, 20)" >
< g transform = "scale(2)" >
< rect width = "200" height = "200" transform = "rotate(45)" />
</ g >
</ g >
</ svg >
-
translate(-10, 20)는 변환 행렬 T1로 계산됩니다.
-
scale(2)는 변환 행렬 T2로 계산됩니다.
-
rotate(45)는 변환 행렬 T3로 계산됩니다.
SVG rect 요소의 CTM은 T1, T2, T3를 순서대로 곱한 결과입니다.
SVG rect 요소의 로컬 좌표계에서 좌표쌍 xlocal, ylocal를 갖는 plocal을 뷰포트 좌표계로 매핑하려면, 해당 요소의 현재 변환 행렬 CTM에 plocal을 포스트 곱셈합니다. 결과는 뷰포트 좌표계에서 좌표쌍 xviewport, yviewport를 갖는 pviewport입니다.
참고: 변환은 시각적 렌더링에는 영향을 주지만, 오버플로우에 영향을 주는 것 외에는 CSS 레이아웃에는 영향을 주지 않습니다. 변환은 getClientRects() 및 getBoundingClientRect() 등 Element 인터페이스 확장에서 노출되는 클라이언트 사각형을 계산할 때도 고려됩니다. 자세한 내용은 [CSSOM-VIEW]를 참조하세요.
div {
height : 100 px ; width : 100 px ;
transform-origin : 50 px 50 px ;
transform : rotate ( 45 deg );
}
transform-origin 속성으로 원점을 X, Y 각각 50픽셀 이동시킵니다. 변환은 원점을 기준으로 요소를 시계 방향으로 45° 회전시킵니다. 모든 변환 함수가 적용된 후, 원점의 이동은 X, Y 각각 -50픽셀만큼 다시 이동됩니다.
div {
height : 100 px ; width : 100 px ;
transform : translate ( 80 px , 80 px ) scale ( 1.5 , 1.5 ) rotate ( 45 deg );
}
시각적으로 div 요소가 왼쪽 아래 방향으로 80px 이동, 150% 확대, 마지막에 45° 회전된 것처럼 보입니다.
각 <transform-function>은 대응하는 4x4 행렬로 나타낼 수 있습니다. div 박스의 좌표 공간에서 부모 요소의 좌표 공간으로 포인트를 매핑하려면, 이 변환들은 역순으로 곱해집니다:
-
회전 행렬을 스케일 행렬에 포스트 곱셈합니다.
-
이전 곱셈 결과에 변환(이동) 행렬을 포스트 곱셈하여 누적 변환 행렬을 만듭니다.
-
마지막으로, 매핑할 포인트를 누적 변환 행렬에 프리 곱셈합니다.
자세한 내용은 변환 함수 목록을 참고하세요.
참고: 동일한 렌더링은 아래처럼 변환을 중첩한 요소를 사용해 구현할 수 있습니다:
< div style = "transform: translate(80px, 80px)" >
< div style = "transform: scale(1.5, 1.5)" >
< div style = "transform: rotate(45deg)" ></ div >
</ div >
</ div >
CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성은 변환된 요소 주변의 콘텐츠 흐름에는 영향을 주지 않습니다. 하지만 오버플로우 영역의 크기는 변환된 요소를 고려합니다. 이 동작은 요소가 상대 위치로 offset될 때와 유사합니다. 따라서 overflow 속성값이 scroll 또는 auto라면, 변환으로 인해 보이는 영역을 벗어난 콘텐츠를 볼 수 있도록 스크롤바가 표시됩니다. 변환은 오버플로우 영역의 크기를 확장할 수 있으며(축소하지는 않음), 이는 변환 적용 전후 요소의 경계 합집합으로 계산됩니다.
CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성이 none이 아닌 값이면 스태킹 컨텍스트가 생성됩니다. 구현체는 부모 스태킹 컨텍스트 내에서 해당 레이어를 z-index: 0인 positioned 요소와 동일한 스태킹 순서로 칠해야 합니다. transform이 적용된 요소가 positioned 요소면 z-index 속성은 [CSS2]에서 설명한 대로 적용되며, 단 auto는 항상 새로운 스태킹 컨텍스트가 생성되므로 0으로 취급합니다.
CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성이 none이 아닌 값이면 해당 요소는 모든 자손의 포함 블록을 생성합니다. padding box는 모든 절대 위치 자손, fixed 위치 자손, 자손 fixed 배경에 대한 레이아웃 기준이 됩니다.
< style >
# container {
width : 300 px ;
height : 200 px ;
border : 5 px dashed black ;
padding : 5 px ;
overflow : scroll ;
}
# bloat {
height : 1000 px ;
}
# child {
right : 0 ;
bottom : 0 ;
width : 10 % ;
height : 10 % ;
background : green ;
}
</ style >
< div id = "container" style = "transform:translateX(5px);" >
< div id = "bloat" ></ div >
< div id = "child" style = "position:fixed;" ></ div >
</ div >
대조 예시
< div id = "container" style = "position:relative; z-index:0; left:5px;" >
< div id = "bloat" ></ div >
< div id = "child" style = "position:absolute;" ></ div >
</ div >
루트 요소의 fixed 배경은 해당 요소에 지정된 transform에 영향을 받습니다. 나머지 transform이 적용된(즉, 자신 또는 조상에 transform이 적용된) 요소에서는 fixed 값의 background-attachment 속성은 scroll로 처리된 것처럼 동작합니다. background-attachment의 계산값은 영향을 받지 않습니다.
참고: 루트 요소에 변환이 적용되면, 해당 변환은 루트 요소에 지정된 모든 배경을 포함하여 캔버스 전체에 적용됩니다. 루트 요소의 배경 페인팅 영역은 전체 캔버스(무한)이므로, 변환에 따라 원래 화면 밖이었던 배경 일부가 화면에 나타날 수 있습니다. 예를 들어, 루트 요소의 배경이 반복되는 점(dots)이고, scale(0.5) 변환이 적용됐다면, 점의 크기는 절반으로 줄지만 그 개수는 두 배가 되어 여전히 전체 뷰포트를 덮게 됩니다.
4. transform 속성
변환은 transform 속성을 통해 요소가 렌더링되는 좌표계에 적용됩니다. 이 속성은 변환 함수 목록을 포함합니다. 좌표계의 최종 변환 값은 목록의 각 함수를 변환 함수의 수학적 설명에 정의된 대로 해당 행렬로 변환한 뒤, 행렬을 곱해서 얻습니다.
이름: | transform |
---|---|
값: | none | <transform-list> |
초기값: | none |
적용 대상: | 변환 가능한 요소 |
상속됨: | 아니오 |
백분율: | 기준 박스의 크기를 참조함 |
계산값: | 지정한 대로, 단 길이는 절대값으로 변환됨 |
정준 순서: | 문법에 따름 |
애니메이션 타입: | transform list, 보간 규칙 참조 |
transform의 계산값이 none이 아닌 경우 포함 블록 및 스태킹 컨텍스트에 영향을 줍니다. 자세한 내용은 §3 변환 렌더링 모델을 참조하세요.
<transform-list> = <transform-function>+
4.1. <transform-function> 직렬화
<transform-function>을 직렬화할 때는 각각의 문법에 따라, 문법에 정의된 순서대로 직렬화하며, 가능한 경우 <calc()> 표현식을 피하고, <calc()> 변환도 피하며, 의미가 바뀌지 않는다면 컴포넌트 생략, 토큰을 공백 하나로 연결, 직렬화된 콤마 뒤에는 공백 하나를 추가합니다.
4.2. <transform-list> 계산값의 직렬화
계산값의 <transform-list>는 다음 알고리즘에 따라 하나의 <matrix()> 함수로 직렬화됩니다:
-
transform을 항등 4x4 행렬로 초기화합니다. transform의 m11, m22, m33, m44 요소는 1로 설정하고, 나머지 요소는 0으로 설정합니다.
-
<transform-function>을 <transform-list>에서 모두 transform에 포스트 곱셈합니다.
-
transform을 <matrix()> 함수로 직렬화합니다.
5. transform-origin 속성
이름: | transform-origin |
---|---|
값: | [ left | center | right | top | bottom | <length-percentage> ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] <length>? | [[ center | left | right ] && [ center | top | bottom ]] <length>? |
초기값: | 50% 50% |
적용 대상: | 변환 가능한 요소 |
상속됨: | 아니오 |
백분율: | 기준 박스의 크기를 참조함 |
계산값: | background-position 참조 |
정준 순서: | 문법에 따름 |
애니메이션 타입: | 계산값 기준 |
transform 속성과 transform-origin 속성의 값은 위에서 설명한 대로 변환 행렬을 계산하는 데 사용됩니다.
값이 하나만 지정된 경우 두 번째 값은 center로 간주합니다. 값이 하나 또는 두 개 지정되면 세 번째 값은 0px으로 간주합니다.
값이 두 개 이상 지정되고 키워드가 없거나 사용된 키워드가 center뿐인 경우 첫 번째 값은 수평 위치(또는 오프셋), 두 번째 값은 수직 위치(또는 오프셋)를 나타냅니다. 세 번째 값은 항상 Z 위치(또는 오프셋)를 나타내야 하며, <length> 타입이어야 합니다.
- <length-percentage>
-
수평 오프셋의 백분율 값은 기준 박스의 너비 기준입니다. 수직 오프셋의 백분율 값은 기준 박스의 높이 기준입니다. 수평 및 수직 오프셋 값은 기준 박스의 왼쪽 상단에서의 오프셋을 나타냅니다.
- <length>
-
길이 값은 고정 길이 오프셋입니다. 수평 및 수직 오프셋 값은 기준 박스의 왼쪽 상단에서의 오프셋을 나타냅니다.
- top
-
수직 위치로 0%로 계산됩니다.
- right
-
수평 위치로 100%로 계산됩니다.
- bottom
-
수직 위치로 100%로 계산됩니다.
- left
-
수평 위치로 0%로 계산됩니다.
- center
-
수평 위치가 별도로 지정되지 않은 경우 50%(left 50%)로 계산되며, 그렇지 않으면 수직 위치는 50%(top 50%)로 계산됩니다.
CSS 레이아웃 박스가 없는 SVG 요소의 초기 사용값은 사용자 에이전트 스타일 시트에 다음이 포함된 것처럼 0 0입니다:
*:not(svg), *:not(foreignObject) > svg {
transform-origin : 0 0 ;
}
transform-origin 속성은 resolved value special case property이며, height와 유사합니다. [CSSOM]
6. 변환 기준 박스: transform-box 속성
이름: | transform-box |
---|---|
값: | content-box | border-box | fill-box | stroke-box | view-box |
초기값: | view-box |
적용 대상: | 변환 가능한 요소 |
상속됨: | 아니오 |
백분율: | 해당 없음 |
계산값: | 지정된 키워드 |
정준 순서: | 문법에 따름 |
애니메이션 타입: | 불연속(discrete) |
transform 및 transform-origin 속성으로 정의되는 모든 변환은 해당 요소의 위치와 크기를 기준으로 하는 기준 박스를 기준으로 상대적으로 적용됩니다. 기준 박스는 다음 중 하나로 지정됩니다:
- content-box
-
콘텐츠 박스를 기준 박스로 사용합니다. 표(table)의 기준 박스는 테이블 래퍼 박스의 테두리 박스(border box)이며, 테이블 박스가 아닙니다.
- border-box
-
테두리 박스를 기준 박스로 사용합니다. 표의 기준 박스도 테이블 래퍼 박스의 테두리 박스입니다.
- fill-box
-
오브젝트 바운딩 박스를 기준 박스로 사용합니다.
- stroke-box
-
스트로크 바운딩 박스를 기준 박스로 사용합니다.
- view-box
-
가장 가까운 SVG 뷰포트를 기준 박스로 사용합니다.
뷰포트를 생성하는 요소에
viewBox
속성이 지정된 경우:
SVG
pattern
요소의 경우, 기준 박스는
patternUnits
속성으로 정의됩니다 [SVG2].
SVG linearGradient 및 radialGradient 요소의 경우, 기준 박스는
gradientUnits
속성으로 정의됩니다 [SVG2].
SVG clipPath 요소의 경우, 기준 박스는
clipPathUnits
속성으로 정의됩니다 [CSS-MASKING].
기준 박스는 transform-origin 속성으로 지정한 원점에 추가 오프셋을 더합니다.
CSS 레이아웃 박스가 없는 SVG 요소의 경우, 사용값은 content-box 대신 fill-box이며, border-box 대신 stroke-box입니다.
CSS 레이아웃 박스가 있는 요소의 경우, 사용값은 fill-box 대신 content-box이고, stroke-box 및 view-box는 border-box입니다.
7. SVG transform 속성
7.1. SVG 표시 속성
transform-origin CSS 속성 역시 표시 속성(presentation attribute)이며, 기존 표시 속성 목록을 확장합니다 [SVG2].
SVG 2는 transform,
patternTransform
,
gradientTransform
속성을 표시 속성으로 정의하며, CSS transform 속성으로 표현됩니다 [SVG2].
CSS 캐스케이드 참여 여부는 SVG 명세에서 표시 속성의 특이성(specificity)에 따라 결정됩니다. SVG에 따르면, 사용자 에이전트는 표시 속성에 대해 새 저자 스타일 시트(author style sheet)를 개념적으로 삽입하며, 이는 저자 스타일 시트 집합 중 첫 번째입니다 [SVG2].
<svg xmlns= "http://www.w3.org/2000/svg" >
<style>
.container {
transform: translate(100px, 100px);
}
</style>
<g class= "container" transform= "translate(200 200)" >
<rect width= "100" height= "100" fill= "blue" />
</g>
</svg>
CSS 캐스케이드 참여로 인해 transform 스타일 속성이 transform 속성보다 우선합니다. 따라서 컨테이너는 200px 대신 수평 및 수직 모두 100px 이동됩니다.
7.2. SVG transform 속성 문법
하위 호환성을 위해 transform,
patternTransform
,
gradientTransform
속성의 문법은 transform CSS 속성의 문법과 다릅니다. 이 속성들에서는 CSS transform 속성에 정의된 추가 <transform-function> 지원이
없습니다. 즉, <translateX()>, <translateY()>, <scaleX()>, <scaleY()>, <skew()>는 transform,
patternTransform
,
gradientTransform
속성에서 지원되지 않습니다.
다음 목록은 transform, patternTransform, gradientTransform 속성의 값을 BNF로 정의하고, 그 뒤에 참고용 철도 다이어그램이 나옵니다. 사용되는 표기는 다음과 같습니다:
-
*: 0회 이상
-
+: 1회 이상
-
?: 0 또는 1회
-
(): 그룹화
-
|: 대안 구분
-
큰따옴표는 리터럴을 감쌉니다. 리터럴은 문자, 왼쪽/오른쪽 괄호로 구성됩니다 [CSS-SYNTAX-3].
-
<number-token>은 CSS Syntax 모듈에서 정의됨 [CSS-SYNTAX-3].
참고: 이 문법은 사용자 에이전트의 구현된 동작을 반영하며, SVG 1.1에서 정의된 문법과 다릅니다.
- 왼쪽 괄호 (
- U+0028 왼쪽 괄호
- 오른쪽 괄호 )
- U+0029 오른쪽 괄호
- 콤마
- U+002C 콤마
- wsp
- U+000A 줄바꿈, U+000D 캐리지 리턴, U+0009 탭, 또는 U+0020 공백
- comma-wsp
-
(wsp+ comma? wsp*) | (comma wsp*)
- translate
-
"translate" wsp* "(" wsp* number ( comma-wsp? number )? wsp* ")"
- scale
-
"scale" wsp* "(" wsp* number ( comma-wsp? number )? wsp* ")"
- rotate
-
"rotate" wsp* "(" wsp* number ( comma-wsp? number comma-wsp? number )? wsp* ")"
- skewX
-
"skewY" wsp* "(" wsp* number wsp* ")"
- skewY
-
"skewY" wsp* "(" wsp* number wsp* ")"
- matrix
-
"matrix" wsp* "(" wsp* number comma-wsp? number comma-wsp? number comma-wsp? number comma-wsp? number comma-wsp? number wsp* ")"
- transform
-
matrix | translate | scale | rotate | skewX | skewY
- transforms
-
transform | transform comma-wsp transforms
- transform-list
-
wsp* transforms? wsp*
7.3. SVG 변환 함수
위의 문법으로 정의된 transform,
patternTransform
,
gradientTransform
속성의 SVG 변환 함수는 아래와 같이 CSS <transform-function>에 매핑됩니다:
SVG 변환 함수 | CSS <transform-function> | 추가 설명 |
---|---|---|
translate | <translate()> | 숫자 값은 CSS <length> 타입으로 해석되며 px 단위가 적용됩니다. |
scale | <scale()> | |
rotate | <rotate()> | 단일 값 버전만 지원. 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다. |
skewX | <skewX()> | 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다. |
skewY | <skewY()> | 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다. |
matrix | <matrix()> |
SVG 변환 함수 rotate에 3개의 값이 있을 경우, 이에 상응하는 CSS <transform-function>으로 매핑할 수 없습니다. 2개의 선택적 숫자 값은 수평 이동 값 cx와 그 다음 수직 이동 값 cy를 나타냅니다. 두 값 모두 CSS <length> 타입으로 해석되며 px 단위를 사용하여 회전의 원점을 정의합니다. 이 동작은 먼저 cx, cy로 이동, 첫 번째 숫자 값으로 <angle> 타입(deg 단위)으로 회전, 그 다음 -cx, -cy로 이동하는 것과 동등합니다.
transform 속성은 CSS 트랜지션의 시작값 또는 끝값이 될 수 있습니다. transform 속성값이 CSS 트랜지션의 시작값 또는 끝값이며 SVG transform list에 3값 rotate 변환 함수가 하나 이상 있으면, 각각의 SVG 변환 함수는 포스트 곱셈되어 결과 행렬을 <matrix()> CSS <transform-function>으로 매핑하고, CSS 트랜지션의 시작/끝값으로 사용해야 합니다.
7.4. 사용자 좌표 공간
pattern
요소에서는
patternTransform
속성 및 transform 속성이 패턴 좌표계에서 추가 변환을 정의합니다. 자세한 내용은
patternUnits
속성을 참고하세요 [SVG2].
linearGradient
및
radialGradient
요소에서는
gradientTransform
속성 및 transform 속성이 그라디언트 좌표계에서 추가 변환을 정의합니다. 자세한 내용은
gradientUnits
속성을 참고하세요 [SVG2].
clipPath
요소에서는 transform 속성 및 transform 속성이 클리핑 경로 좌표 공간에서 추가 변환을 정의합니다. 자세한
내용은
clipPathUnits
속성을 참고하세요 [CSS-MASKING].
그 외의 변환 가능한 요소에서는 transform 속성 및 transform 속성이 부모의 현재 사용자 좌표계에서 변환을 정의합니다. transform 속성의 모든 백분율 값은 해당 요소의 기준 박스를 기준으로 합니다.
다음 예제에서 패턴의 transform-origin 속성은 수평과 수직 모두 50%만큼 원점을 이동시킵니다. transform 속성은 절대 길이로 이동도 지정합니다.
<svg xmlns= "http://www.w3.org/2000/svg" >
<style>
pattern {
transform: rotate(45deg);
transform-origin: 50% 50%;
}
</style>
<defs>
<pattern id= "pattern-1" >
<rect id= "rect1" width= "100" height= "100" fill= "blue" />
</pattern>
</defs>
<rect width= "200" height= "200" fill= "url(#pattern-1)" />
</svg>
SVG
pattern
요소는 바운딩 박스가 없습니다. 참조하는 기준 박스는
rect
요소의 기준 박스를 사용하여 transform-origin의 상대값을 해결합니다.
따라서 원점은 임시로 100픽셀 이동되어 패턴 요소 콘텐츠의 사용자 공간을 회전시킵니다.
7.5. SVG DOM 인터페이스 (transform 속성)
SVG 명세는 SVG DOM에서 SVG SVGAnimatedTransformList
인터페이스를 정의하여 SVG transform,
gradientTransform
및
patternTransform
속성의 애니메이션 값과 기본 값을 제공하도록 합니다. 하위 호환성을 보장하기 위해 이 API는 사용자 에이전트에서 계속 지원되어야 합니다.
baseVal
은 작성자가 SVG transform,
patternTransform
,
gradientTransform
속성의 값을 접근 및 수정할 수 있게 합니다. SVG DOM의 하위 호환성을 제공하기 위해 baseVal
은 이
저자 스타일 시트의 값을 반영해야 합니다. baseVal
의 SVG DOM 객체를 수정하면 즉시 저자 스타일
시트에 반영되어야 합니다.
animVal
은 transform 속성의 계산 스타일을 나타냅니다. 따라서 적용된 모든 CSS3 트랜지션, CSS3 애니메이션 또는 SVG 애니메이션이 있을 경우 모두
포함됩니다. 계산 스타일 및 animVal
의 SVG DOM 객체는 수정할 수 없습니다.
8. SVG 애니메이션
8.1.
animate
및
set
요소
이 명세에서는
animate
요소와
set
요소가 <transform-list> 데이터 타입을 애니메이션할 수 있습니다.
애니메이션 효과는 포스트 곱셈(post-multiplied)으로 아래 값에 적용되며, <transform-list> 애니메이션의 특수한 동작 때문에, 아래 값에 더하는 것이 아니라 곱해집니다(아래 참고).
From-to, from-by, by 애니메이션은 SMIL에서 해당 values 애니메이션과 동등하게 정의됩니다. 그러나 to 애니메이션은 가산적(additive) 및 비가산적(non-additive) 동작이 혼합되어 있습니다 [SMIL3].
animate
요소의 to 애니메이션은 아래 값에서 to 속성 값으로 부드럽게 변화하는 특별한 기능을 제공합니다. 그러나 이는 가산적 변환 애니메이션이 포스트 곱셈이어야 한다는 요구와 수학적으로 충돌합니다.
결과적으로
animate
요소의 to 애니메이션 동작은 정의되지 않습니다. 저자는 원하는 변환 애니메이션을 위해 from-to, from-by, by,
values 애니메이션을 사용할 것을 권장합니다.
데이터 타입 <transform-list>의 애니메이션에서
calcMode
속성에 "paced" 값을 지정하면 정의되지 않습니다. 지정된 경우 UA는 "linear" 값을
선택할 수 있습니다. 향후 명세에서는 <transform-list>에 대해
pace 애니메이션 방법을 정의할 수 있습니다.
참고: 아래 단락들은 애니메이션 가능한 요소, 속성, 프로퍼티 [SVG11]를 확장합니다.
도입된 표시 속성 transform,
patternTransform
,
gradientTransform
및 transform-origin은 애니메이션 가능합니다.
이 명세에서 SVG 기본 데이터 타입 <transform-list>는 <transform-function> 목록과
동등합니다. <transform-list>는 애니메이션 및 가산적입니다. 이
데이터 타입은 SVG
animate
요소와 SVG
set
요소를 사용해 애니메이션할 수 있습니다. SVG 애니메이션은 변환 값 간의 트랜지션 및 애니메이션 절에 설명된 것과 동일한
애니메이션 단계를 따라야 합니다.
데이터 타입 | 가산적? |
animate
|
set
|
animateColor
|
animateTransform
| 설명 |
---|---|---|---|---|---|---|
<transform-list> | 예 | 예 | 예 | 아니오 | 예 |
animateTransform
에서 가산적(additive)이란 변환이 기본 변환 집합에 포스트 곱셈된다는 의미입니다.
|
8.2. 가산의 중립 원소
일부 애니메이션은 가산의 중립 원소가 필요합니다. 변환 함수의 경우 이는 0의 스칼라 또는 스칼라 리스트입니다. 변환 함수의 중립 원소 예시는 translate(0), scale(0), rotate(0), skewX(0), skewY(0) 등이 있습니다.
참고: 이 단락은 [SMIL] 요구사항 및 [SVG11]에서 정의한 확장에 집중합니다. 이 명세는 위에 나열된 함수 이외의 다른 변환 함수에 대한 중립 원소 정의를 제공하지 않습니다.
by 값 vb로 by 애니메이션을 수행하는 것은, 대상 속성의 도메인(0으로 표기)의 가산 중립 원소와 vb를 values 리스트에 넣고 additive="sum"으로 지정하는 것과 동일합니다. [SMIL3]
<rect width= "100" height= "100" >
<animateTransform attributeName= "transform" attributeType= "XML"
type= "scale" by= "1" dur= "5s" fill= "freeze" />
</rect>
type="scale"로 by 애니메이션을 수행할 때의 가산 중립 원소는 값 0입니다. 즉, 위 예제의 애니메이션을 수행하면 0초에 사각형이 보이지 않고(애니메이션된 변환 리스트 값이 scale(0)이므로), 5초에 원래 크기로 복귀합니다(애니메이션된 변환 리스트 값이 scale(1)이므로).
8.3. SVG 1.1 'attributeName' 속성
SVG 1.1 애니메이션은 "attributeName" 속성을 정의하여 대상 속성의 이름을 지정합니다.
표시 속성
gradientTransform
및
patternTransform
에도 transform 값을 사용할 수 있습니다. 동일한 transform 속성이 애니메이션됩니다.
이 예에서는 linear gradient의 gradient 변환이 애니메이션됩니다.
<linearGradient gradientTransform= "scale(2)" >
<animate attributeName= "gradientTransform" from= "scale(2)" to= "scale(4)"
dur= "3s" additive= "sum" />
<animate attributeName= "transform" from= "translate(0, 0)" to= "translate(100px, 100px)"
dur= "3s" additive= "sum" />
</linearGradient>
linearGradient
요소는
gradientTransform
표시 속성을 지정합니다. 두 개의
animate
요소는
gradientTransform
과 transform 속성을 대상으로 지정합니다. 모든 애니메이션은 동일한 gradient 변환에 적용되며, 첫 번째 애니메이션의
스케일링을 적용한 후 두 번째 애니메이션의 이동을 순차적으로 적용합니다.
9. 변환 함수
transform 속성의 값은 <transform-function> 목록입니다. 허용되는 변환 함수 집합은 아래와 같습니다. 아래 함수에서 <zero>는 0deg와 동일하게 동작합니다("단위 없는 0" 각도는 레거시 호환성 유지를 위해 보존됨). 수평 이동의 백분율은 기준 박스의 너비를 기준으로 합니다. 수직 이동의 백분율은 기준 박스의 높이를 기준으로 합니다.
9.1. 2D 변환 함수
- matrix() = matrix( <number> [, <number> ]{5,5} )
-
여섯 값 a, b, c, d, e, f의 변환 행렬 형태로 2D 변환을 지정합니다.
- translate() = translate( <length-percentage> [, <length-percentage> ]? )
-
벡터 [tx, ty]에 의해 2D 이동을 지정합니다. tx는 첫 번째 이동값 매개변수이고, ty는 선택적 두 번째 이동값 매개변수입니다. <ty>가 제공되지 않으면, ty 값은 0입니다.
- translateX() = translateX( <length-percentage> )
-
주어진 값만큼 X 방향으로 이동을 지정합니다.
- translateY() = translateY( <length-percentage> )
-
주어진 값만큼 Y 방향으로 이동을 지정합니다.
- scale() = scale( <number> [, <number> ]? )
-
두 매개변수로 설명되는 [sx,sy] 스케일링 벡터에 의해 2D 스케일 동작을 지정합니다. 두 번째 매개변수가 없으면 첫 번째와 동일한 값을 가집니다. 예를 들어, scale(1, 1)은 요소에 아무런 변화가 없고, scale(2, 2)는 X, Y축 모두 두 배로 보이므로 일반 기하학적 크기의 네 배가 됩니다.
- scaleX() = scaleX( <number> )
-
sx를 매개변수로 사용하여 [sx,1] 스케일링 벡터로 2D 스케일 동작을 지정합니다.
- scaleY() = scaleY( <number> )
-
sy를 매개변수로 사용하여 [1,sy] 스케일링 벡터로 2D 스케일 동작을 지정합니다.
- rotate() = rotate( [ <angle> | <zero> ] )
-
매개변수로 지정된 각도만큼, transform-origin 속성에 정의된 원점을 기준으로 2D 회전을 지정합니다. 예를 들어 rotate(90deg)는 요소를 시계 방향으로 4분의 1 회전시킵니다.
- skew() = skew( [ <angle> | <zero> ] [, [ <angle> | <zero> ] ]? )
-
X와 Y에 대해 [ax,ay]로 2D 기울이기(skew)를 지정합니다. 두 번째 매개변수가 없으면 0 값입니다.
skew()는 호환성 유지를 위해 존재하며, 새로운 콘텐츠에서는 사용하지 않는 것이 좋습니다. 대신 skewX() 또는 skewY()를 사용하세요. skew()의 동작은 skewX()와 skewY()를 곱한 것과 다름에 유의하세요.
- skewX() = skewX( [ <angle> | <zero> ] )
-
주어진 각도로 X축 방향 2D 기울이기(skew) 변환을 지정합니다.
- skewY() = skewY( [ <angle> | <zero> ] )
-
주어진 각도로 Y축 방향 2D 기울이기(skew) 변환을 지정합니다.
9.2. 변환 함수 원시 및 파생 함수
일부 변환 함수는 더 일반적인 변환 함수로 표현할 수 있습니다. 이러한 변환 함수는 파생 변환 함수(derived transform functions)라 하며, 일반 변환 함수는 원시 변환 함수(primitive transform functions)라 합니다. 2차원 원시 및 파생 변환 함수는 다음과 같습니다:
- translate()
- <translateX()>, <translateY()>, <translate()>의 원시 함수입니다.
- scale()
- <scaleX()>, <scaleY()>, <scale()>의 원시 함수입니다.
10. 변환 함수 목록
<transform-function> 목록이 제공되면, 각 변환 함수가 지정된 순서대로 개별적으로 지정된 것과 동일한 효과가 있습니다.
즉, 위치와 크기에 영향을 주는 다른 스타일이 없는 경우, 중첩된 변환 집합은 하나의 변환 함수 목록과 동일하며, 조상 좌표계에서 해당 요소의 로컬 좌표계로 적용됩니다. 결과 변환은 목록의 변환들을 행렬 곱셈한 값입니다.
< div style = "transform: translate(-10px, -20px) scale(2) rotate(45deg)" />
는 다음과 기능적으로 동일합니다:
< div style = "transform: translate(-10px, -20px)" id = "root" >
< div style = "transform: scale(2)" >
< div style = "transform: rotate(45deg)" >
</ div >
</ div >
</ div >
변환 함수로 인해 객체의 현재 변환 행렬이 역행렬 불가능(non-invertible)이 되면, 해당 객체와 그 콘텐츠는 표시되지 않습니다.
다음 예시의 객체는 0으로 스케일됩니다.
< style >
. box {
transform : scale( 0 );
}
</ style >
< div class = "box" >
Not visible
</ div >
스케일링으로 인해 div 박스의 좌표 공간에서 역행렬 불가능한 CTM이 생성됩니다. 따라서 div 박스와 그 안의 텍스트는 표시되지 않습니다.
11. 변환의 보간
보간은 다음과 같이 수행됩니다:
-
Va와 Vb가 모두
none이면:
-
Vresult는 none입니다.
-
-
none을 길이 0의 목록으로
취급하면,
Va 또는 Vb의 길이가 다를 경우:
-
짧은 목록을 긴 목록의 길이로 확장하고, 추가된 각 위치의 함수는 긴 목록의 해당 위치 함수와 동일한 항등 변환 함수로 설정합니다. 두 변환 함수 목록은 다음 규칙에 따라 보간됩니다.
-
-
Vresult를 빈 목록으로 둡니다.
Va와 Vb의 처음부터 각 위치의 함수를 비교합니다:
-
함수 이름이 같거나 원시 변환 함수의 파생형이면, §12 원시 및 파생 변환 함수의 보간에 설명된 대로 보간하여 Vresult에 추가합니다.
-
함수 쌍이 이름 또는 원시 변환 함수가 다르면, 각 Va, Vb의 남은 변환 함수를 각각 포스트 곱셈하여 4x4 행렬 두 개를 만듭니다. 보간은 §13 행렬의 보간에 따라 두 행렬을 보간하고, 결과를 Vresult에 추가한 뒤, Va와 Vb의 반복을 중단합니다.
예시: Va가 rotate(0deg) scale(1) translate(20px)이고 Vb가 rotate(270deg) translate(10px) scale(2)이라면, rotate(0deg)와 rotate(360deg) 함수는 §12 원시 및 파생 변환 함수의 보간에 따라 보간되고, 나머지 목록—scale(1) translate(20px)와 translate(10px) scale(2)— 는 먼저 4x4 행렬로 변환된 뒤 §13 행렬의 보간에 따라 보간됩니다. 이전 명세에서는 목록의 모든 함수가 일치하지 않으면 일치하는 쌍의 변환 함수 보간을 시도하지 않았습니다. 이 예시의 두 목록은 행렬 보간만 사용되었으며, 두 번째 목록의 rotate(360deg) 컴포넌트가 손실됐습니다.
-
특정 경우, 애니메이션으로 인해 변환 행렬이 특이(singular)하거나 역행렬 불가능(non-invertible)하게 될 수 있습니다. 예를 들어 scale이 1에서 -1로 이동하는 애니메이션. 이때 행렬이 그런 상태에 있으면 변환된 요소는 렌더링되지 않습니다.
12. 원시 및 파생 변환 함수의 보간
이름과 인수 개수가 같은 두 변환 함수는 변환 없이 수치적으로 보간됩니다. 계산된 값은 동일한 변환 함수 타입과 동일한 인수 개수를 가집니다. <matrix()>에는 특별 규칙이 적용됩니다.
translate(0)과 translate(100px) 두 변환 함수는 타입이 같고 인수 개수도 같으므로 수치적으로 보간할 수 있습니다. translateX(100px)는 타입이 다르고 translate(100px, 0)는 인수 개수가 달라서 변환 함수 변환 없이는 보간할 수 없습니다.
같은 원시를 공유하는 서로 다른 타입의 변환 함수, 혹은 같은 타입이지만 인수 개수가 다른 변환 함수도 보간 가능합니다. 두 변환 함수 모두 먼저 공통 원시로 변환한 후 수치적으로 보간됩니다. 계산된 값은 보간된 인수를 포함한 원시 함수입니다.
다음 예시는 div 박스에 마우스를 올릴 때 translateX(100px)에서 translateY(100px)으로 3초간 전환되는 트랜지션을 설명합니다. 두 변환 함수 모두 같은 원시 translate()에서 파생되므로 보간 가능합니다.
div {
transform : translateX ( 100 px );
}
div:hover {
transform : translateY ( 100 px );
transition : transform 3 s ;
}
트랜지션 기간 동안 두 변환 함수 모두 공통 원시로 변환됩니다. translateX(100px)는 translate(100px, 0)으로, translateY(100px)는 translate(0, 100px)으로 변환됩니다. 이후 두 변환 함수는 수치적으로 보간될 수 있습니다.
두 변환 함수가 2차원 공간에서 원시를 공유하면, 두 변환 함수 모두 2차원 원시로 변환됩니다. 변환 함수 중 하나 또는 둘 다 3차원 변환 함수라면, 공통 3차원 원시가 사용됩니다.
이 예시는 2차원 변환 함수가 3차원 변환 함수로 애니메이션되는 경우입니다. 공통 원시는 translate3d()입니다.
div {
transform : translateX ( 100 px );
}
div:hover {
transform : translateZ ( 100 px );
transition : transform 3 s ;
}
먼저 translateX(100px)는 translate3d(100px, 0, 0)으로, translateZ(100px)는 translate3d(0, 0, 100px)으로 변환됩니다. 이후 두 변환 함수는 수치적으로 보간됩니다.
13. 행렬의 보간
두 행렬 사이를 보간할 때, 각 행렬은 대응하는 이동, 회전, 스케일, 기울기(skew)로 분해됩니다. 분해된 행렬의 각 컴포넌트는 수치적으로 보간되어 마지막 단계에서 행렬로 다시 합성됩니다.
< style >
div {
transform : rotate( 45 deg );
}
div : hover {
transform : translate( 100 px , 100 px ) rotate( 1215 deg );
transition : transform 3 s ;
}
</ style >
< div ></ div >
소스 변환 rotate(45deg)의 변환 함수 개수가 대상 변환 translate(100px, 100px) rotate(1125deg)의 함수 개수와 다릅니다. 변환의 보간 마지막 규칙에 따라 두 변환 모두 행렬 보간을 사용해야 합니다. 변환 함수를 행렬로 변환하면 세 번 회전 정보가 사라지고 요소는 1/4 회전(90°)만 수행됩니다.
위와 같이 3과 1/4 회전을 얻으려면, 소스와 대상 변환 모두 변환의 보간의 세 번째 규칙을 충족해야 합니다. 소스 변환은 translate(0, 0) rotate(45deg)와 같이 작성해야 변환 함수의 선형 보간이 가능합니다.
아래에서는 2D 행렬의 보간과 행렬 중 하나라도 2D 행렬이 아닌 경우의 행렬 보간을 구분합니다.
보간에 사용되는 행렬 중 하나가 역행렬 불가능한 경우, 사용되는 애니메이션 함수는 해당 애니메이션 명세의 규칙에 따라 불연속 애니메이션(discrete animation)으로 대체되어야 합니다.
13.1. 지원 함수
다음 섹션의 의사 코드는 아래 지원 함수를 사용합니다:
지원 함수(point는 3컴포넌트 벡터, matrix는 4x4 행렬, vector는 4컴포넌트 벡터): double determinant(matrix) matrix의 4x4 행렬식 반환 matrix inverse(matrix) 전달된 행렬의 역행렬 반환 matrix transpose(matrix) 전달된 행렬의 전치행렬 반환 point multVecMatrix(point, matrix) point를 matrix에 곱하여 변환된 point 반환 double length(point) 벡터의 길이 반환 point normalize(point) point를 길이 1로 정규화 double dot(point, point) 두 point의 내적 반환 double sqrt(double) 값의 제곱근 반환 double max(double y, double x) 두 값 중 더 큰 값 반환 double dot(vector, vector) 두 vector의 내적 반환 vector multVector(vector, vector) 두 vector 곱셈 double sqrt(double) 값의 제곱근 반환 double max(double y, double x) 두 값 중 더 큰 값 반환 double min(double y, double x) 두 값 중 더 작은 값 반환 double cos(double) 값의 코사인 반환 double sin(double) 값의 사인 반환 double acos(double) 값의 아크코사인 반환 double abs(double) 값의 절대값 반환 double rad2deg(double) 라디안을 도 단위로 변환해 반환 double deg2rad(double) 도 단위를 라디안으로 변환해 반환 분해에는 다음 함수도 사용됨: point combine(point a, point b, double ascl, double bscl) result[0] = (ascl * a[0]) + (bscl * b[0]) result[1] = (ascl * a[1]) + (bscl * b[1]) result[2] = (ascl * a[2]) + (bscl * b[2]) return result
13.2. 2D 행렬의 보간
13.2.1. 2D 행렬 분해
아래 의사 코드는 "Graphics Gems II, Jim Arvo 편집"의 "unmatrix" 방법에 기반합니다.
의사 코드의 행렬은 컬럼 우선(column-major) 순서를 사용합니다. 행렬 항목의 첫 번째 인덱스는 컬럼, 두 번째 인덱스는 행을 나타냅니다.
입력: matrix ; 4x4 행렬 출력: translation ; 2컴포넌트 벡터 scale ; 2컴포넌트 벡터 angle ; 회전 m11 ; 2x2 행렬의 1,1 m12 ; 2x2 행렬의 1,2 m21 ; 2x2 행렬의 2,1 m22 ; 2x2 행렬의 2,2 분해 불가시 false, 가능하면 true 반환 double row0x = matrix[0][0] double row0y = matrix[0][1] double row1x = matrix[1][0] double row1y = matrix[1][1] translate[0] = matrix[3][0] translate[1] = matrix[3][1] scale[0] = sqrt(row0x * row0x + row0y * row0y) scale[1] = sqrt(row1x * row1x + row1y * row1y) // 행렬식이 음수면 한 축이 뒤집힘. double determinant = row0x * row1y - row0y * row1x if (determinant < 0) // 최소 단위벡터 내적이 작은 축을 뒤집기. if (row0x < row1y) scale[0] = -scale[0] else scale[1] = -scale[1] // 스케일 제거를 위해 행렬 재정규화. if (scale[0]) row0x *= 1 / scale[0] row0y *= 1 / scale[0] if (scale[1]) row1x *= 1 / scale[1] row1y *= 1 / scale[1] // 회전 계산 및 행렬 재정규화. angle = atan2(row0y, row0x); if (angle) // Rotate(-angle) = [cos(angle), sin(angle), -sin(angle), cos(angle)] // = [row0x, -row0y, row0y, row0x] // 위 정규화 덕분에. double sn = -row0y double cs = row0x double m11 = row0x double m12 = row0y double m21 = row1x double m22 = row1y row0x = cs * m11 + sn * m21 row0y = cs * m12 + sn * m22 row1x = -sn * m11 + cs * m21 row1y = -sn * m12 + cs * m22 m11 = row0x m12 = row0y m21 = row1x m22 = row1y // 회전 함수가 도 단위를 기대하므로 변환. angle = rad2deg(angle) return true
13.2.2. 분해된 2D 행렬 값의 보간
두 분해된 2D 행렬 값을 보간하기 전에 다음을 수행합니다
입력: translationA ; 2컴포넌트 벡터 scaleA ; 2컴포넌트 벡터 angleA ; 회전 m11A ; 2x2 행렬의 1,1 m12A ; 2x2 행렬의 1,2 m21A ; 2x2 행렬의 2,1 m22A ; 2x2 행렬의 2,2 translationB ; 2컴포넌트 벡터 scaleB ; 2컴포넌트 벡터 angleB ; 회전 m11B ; 2x2 행렬의 1,1 m12B ; 2x2 행렬의 1,2 m21B ; 2x2 행렬의 2,1 m22B ; 2x2 행렬의 2,2 // 하나는 x축, 다른 하나는 y축이 뒤집혔다면, // 뒤집히지 않은 회전으로 변환. if ((scaleA[0] < 0 && scaleB[1] < 0) || (scaleA[1] < 0 && scaleB[0] < 0)) scaleA[0] = -scaleA[0] scaleA[1] = -scaleA[1] angleA += angleA < 0 ? 180 : -180 // 긴 방향으로 돌지 않도록. if (!angleA) angleA = 360 if (!angleB) angleB = 360 if (abs(angleA - angleB) > 180) if (angleA > angleB) angleA -= 360 else angleB -= 360
이후, 소스 행렬의 분해값 translation, scale, angle, m11~m22의 각 컴포넌트는 대상 행렬의 해당 컴포넌트와 선형적으로 보간됩니다.
13.2.3. 2D 행렬로 재합성
보간 후, 결과값은 요소의 사용자 공간 변환에 사용됩니다. 한 가지 방법은 이 값들을 다시 4x4 행렬로 합성하는 것입니다. 아래 의사 코드에 따라 수행할 수 있습니다.
의사 코드의 행렬은 컬럼 우선(column-major) 순서를 사용합니다. 행렬 항목의 첫 번째 인덱스는 컬럼, 두 번째 인덱스는 행을 나타냅니다.
입력: translation ; 2컴포넌트 벡터 scale ; 2컴포넌트 벡터 angle ; 회전 m11 ; 2x2 행렬의 1,1 m12 ; 2x2 행렬의 1,2 m21 ; 2x2 행렬의 2,1 m22 ; 2x2 행렬의 2,2 출력: matrix ; 항등 행렬로 초기화된 4x4 행렬 matrix[0][0] = m11 matrix[0][1] = m12 matrix[1][0] = m21 matrix[1][1] = m22 // 행렬 이동. matrix[3][0] = translate[0] * m11 + translate[1] * m21 matrix[3][1] = translate[0] * m12 + translate[1] * m22 // 행렬 회전. angle = deg2rad(angle); double cosAngle = cos(angle); double sinAngle = sin(angle); // 임시, 항등 행렬로 초기화된 4x4 행렬 rotateMatrix rotateMatrix[0][0] = cosAngle rotateMatrix[0][1] = sinAngle rotateMatrix[1][0] = -sinAngle rotateMatrix[1][1] = cosAngle matrix = post-multiply(rotateMatrix, matrix) // 행렬 스케일. matrix[0][0] *= scale[0] matrix[0][1] *= scale[0] matrix[1][0] *= scale[1] matrix[1][1] *= scale[1]
14. 변환 함수의 수학적 설명
수학적으로, 모든 변환 함수는 다음 형태의 4x4 변환 행렬로 표현될 수 있습니다:
행렬의 한 translate 단위는 요소의 로컬 좌표계에서 1픽셀에 해당합니다.
-
6개의 매개변수 a, b, c, d, e, f를 가진 2D 3x2 행렬은 다음 행렬과 같습니다:
-
매개변수 tx, ty를 가진 2D 이동(translation)은 tz 값이 0인 3D 이동과 같습니다.
-
매개변수 sx, sy를 가진 2D 스케일(scale)은 sz 값이 1인 3D 스케일과 같습니다.
-
매개변수 alpha를 가진 2D 회전(rotation)은 벡터 [0,0,1] 및 매개변수 alpha를 사용하는 3D 회전과 같습니다.
-
매개변수 alpha, beta를 가진 2D 기울이기(skew) 변환은 다음 행렬과 같습니다:
-
매개변수 alpha를 사용하는 X축 방향의 2D 기울이기(skew) 변환은 다음 행렬과 같습니다:
-
매개변수 beta를 사용하는 Y축 방향의 2D 기울이기(skew) 변환은 다음 행렬과 같습니다:
15. 프라이버시 및 보안 고려사항
UA는 공격자가 정보를 유추하거나 타이밍 공격을 할 수 없도록 변환 연산을 구현해야 합니다.타이밍 공격이란, 연산이 수행되는 시간 차이를 분석하여 보호된 콘텐츠 정보를 얻는 방법입니다.
현재 이 명세에 특화된 잠재적 프라이버시 또는 보안 문제에 대한 정보는 없습니다.
변경 사항
2018년 11월 30일 워킹 드래프트 이후
-
실질적인 변경 없음
-
CR용 보일러플레이트, 스타일 업데이트
2017년 11월 30일 워킹 드래프트 이후
-
patternTransform, gradientTransform 표시 속성이 transform 속성을 대표한다는 명세 본문을 삭제함. 해당 내용은 SVG 2 [SVG2]에서 규정할 예정.
-
프라이버시 및 보안 섹션 추가.
-
[SVG2] 정의에 따라 transformable elements 기준 사용.
-
transform,
gradientTransform
및patternTransform
속성의 특수 문법 추가. -
의사 코드에서 행렬 항목 인덱스 순서 명확화.
-
재합성 의사 코드에서 곱셈 순서 명확화.
-
transform의 overflow 영역 동작 명확화.
-
translateX(0), translateY(0), scaleX(0), scaleY(0)를 중립 원소 목록에서 제거.
-
변환 함수 정의에서 3D 변환 관련 참조 제거.
-
공통 접두사가 있는 두 <transform-list> 길이 맞추기 및 행렬 보간을 피하는 보간 명세.
-
교체되지 않은 인라인 박스, table-column 박스, table-column-group 박스에는 transform 적용 안 됨.
-
pattern
,linearGradient
,radialGradient
및clipPath
요소의 변환 대상 좌표 공간 정의. -
변환 함수 원시에서 3값 <rotate()> 제거.
-
transformation matrix와 current transformation matrix 계산 명확화.
-
페인트 서버 및
clipPath
요소의 기준 박스 정의. -
트랜지션 시작/끝값으로 3값 rotate를 가진 transform 표시 속성 동작 명세.
-
stroke-box, content-box를 transform-box에 추가. 모든 명세 간 박스 매핑 동작 일치.
-
편집상 변경.
감사의 글
편집자들은 Robert O’Callahan, Cameron McCormack, Tab Atkins, Gérard Talbot, L. David Baron, Rik Cabanier, Brian Birtles, Benoit Jacob, Ken Shoemake, Alan Gresley, Maciej Stochowiak, Sylvain Galineau, Rafal Pietrak, Shane Stephens, Matt Rakow, XiangHongAi, Fabio M. Costa, Nivesh Rajbhandari, Rebecca Hauck, Gregg Tavares, Graham Clift, Erik Dahlström, Alexander Zolotov, Amelia Bellamy-Royds, Boris Zbarsky에게 꼼꼼한 리뷰, 코멘트, 수정에 대해 감사드립니다.