SVG 좌표 변형

이 항목에서는 getScreenCTM() 메서드와 연결된 SVG 좌표 변형에 대해 설명합니다.

SVG 좌표 및 변형은 큰 주제입니다. 이 주제에 대한 정보는 W3C SVG 사양 중 특히 좌표계, 변형 및 단위에서 찾을 수 있습니다.

이 항목에서는 SVG 좌표와 관련하여 특히 치명적인 문제, 즉 화면 좌표(기술적으로, 초기 뷰포트 좌표계)의 특정 점을 지정된 SVG 요소와 관련된 좌표계(기술적으로, 현재 사용자 좌표계)에 매핑하는 문제를 다룹니다. 예를 들어, 표준 데카르트 좌표계를 사용하는 SVG 원을 생각해 보세요.

표준 데카르트 좌표계를 사용하는 SVG 원

그림 1

이 예에서 우리가 관심을 갖는 것은 원의 좌표계에 대해 상대적인 마우스의 위치를 결정하는 것입니다. 따라서 다음 그림에서 제안하는 대로 마우스의 화면 좌표를 원의 데카르트 좌표에 매핑해야 합니다.

마우스 좌표가 데카르트 좌표에 매핑된 SVG 원

그림 2

그림 2에서 마우스에는 (843, 270)이라는 화면 좌표가 있습니다. 이 점이 원의 좌표계에 매핑되면 마우스 좌표는 (175, 175)가 됩니다.

참고  

행렬이나, 행렬 곱셈 또는 역행렬 계산에 대해 익숙하지 않은 경우에는 진행하기 전에 다음 중 하나 이상을 살펴 보세요.

그림 2의 변형을 수학적으로 설명하기 위해서는 몇 가지 정의부터 시작하는 것이 도움이 됩니다. W3C SVG 사양에는 다음과 같은 내용이 포함되어 있습니다.

변형 행렬은 한 좌표계에서 다른 좌표계로의 수학적 매핑을 정의합니다. CTM(current transformation matrix)은 다음 등식을 통한 3x3 CTM 행렬을 사용하여 사용자 좌표계에서 뷰포트 좌표계로의 매핑을 정의합니다.

좌표 변형 수식

각 항목은 다음을 의미합니다.

  • M은 CTM(current transformation matrix)입니다.
  • 동차 벡터은 점 (x, y)를 사용자 좌표계로 나타내는 동차 벡터입니다. 그림 2에서 이 벡터는 행렬 형식의 점 (175, 175)이며 "원(circle) 점" (175, 175)와 같습니다. 동차 벡터의 "1"은 행렬 연산을 위한 것으로서 무시할 수 있습니다.
  • 준비된 동차 벡터은 점 (x, y)를 뷰포트 좌표계로 나타내는 동차 벡터입니다. 그림 2에서 이 벡터는 행렬 형식의 점 (843, 270)이며 "화면 점" (843, 270)과 같습니다.

다행히 CTM은 getScreenCTM() 메서드를 호출하여 JavaScript로 얻을 수 있습니다. 예를 들어 그림 2의 원이 svgCircle이라고 하면 var M = svgCircle.getScreenCTM()은 적절한 행렬 M을 반환하고 앞의 등식을 사용하여 원 점을 화면 점으로 변환할 것입니다. 즉, 그림 2의 CTM M은 다음과 같습니다.

그림 2의 CTM

그런 다음 원 좌표 (175, 175)를 다음과 같이 화면 좌표 (843, 270)에 매핑할 수 있습니다.

CTM의 응용

이것은 반올림 후 화면 좌표 (843, 270)이 됩니다.

앞의 예는 원 좌표를 화면 좌표로 변형하는 방법을 보여 줍니다. 그러면 그 반대는 어떻습니까? 즉, 화면 좌표가 주어진 경우 해당 원 좌표는 무엇입니까? 이 문제에 답하려면 x, y 벡터에 대해 좌표 변형 수식을 풀어야 합니다. 이것은 다음과 같이 완료할 수 있습니다.

행렬 수식 해법

각 항목은 다음을 의미합니다.

  • M-1은 CTM 행렬의 역행렬로서 위 예제의 경우 거의 예: 역 CTM과 같습니다. 모든 허용된 SVG 좌표 변형은 2D 공간을 또 다른 2D 공간으로 매핑하므로 M은 항상 역행렬로 만들 수 있습니다.
  • I는 3x3 항등 행렬을 나타냅니다(M-1 = I임).

이렇게 해서 유도된 등식 역행렬 수식을 사용하여 화면 좌표 (843, 270)을 다음과 같이 해당 원 좌표로 매핑할 수 있습니다.

역행렬 해법

이것은 반올림 후 원 좌표 (175, 175)가 됩니다.

이렇게 수학적으로 제대로 이해하고 JavaScript로 역행렬 수식을 구현하는 것은 상대적으로 간단합니다:


function coordinateTransform(screenPoint, someSvgObject)
{
  var CTM = someSvgObject.getScreenCTM();
  return screenPoint.matrixTransform( CTM.inverse() );
}

이 함수는 화면 점(SVGPoint 유형)과, 원과 같은 일부 SVG 개체가 있을 경우 화면 점을 someSvgObject와 연관된 좌표계에 매핑합니다. someSvgObject가 그림 2의 원을 나타내는 경우,

  • var CTM = someSvgObject.getScreenCTM()은 현재 화면 및 원 크기와 연관된 CTM을 가져옵니다.
  • CTM.inverse()는 CTM 행렬을 도치시켜 앞의 수식에서 M-1을 만듭니다.
  • screenPoint.matrixTransform( CTM.inverse() )M-1과 주어진 화면 좌표 화면 좌표 행렬(즉, screenPoint)을 곱하여 필요한 원 좌표 원 좌표 행렬을 산출합니다.

그림 2와 연관된 전체 샘플을 보려면 Liquid SVG를 클릭하세요. 이 샘플과 연결된 소스 코드를 보려면 브라우저의 소스 보기 기능을 사용하세요. 예를 들어, Windows Internet Explorer에서는 웹 페이지를 마우스 오른쪽 단추로 클릭하고 소스 보기를 선택합니다. 이 문서의 나머지 내용을 확인할 때 사용 가능한 소스 코드가 있는지 확인하세요.

브라우저 창의 크기를 변경하면 원의 크기도 그에 따라 조정됩니다. 이 유동적 레이아웃은 다음 퍼센트 기반 값의 결과입니다.


html {
  padding: 0;
  margin: 0;
  height: 100%; /* Required for liquidity. */  
}

body {
  padding: 0;
  margin: 0;
  height: 100%; /* Required for liquidity. */
}


<!-- width="100%" and height="98%" required for liquidity. -->
<svg id="svgElement" width="100%" height="98%" viewbox="0 0 800 800">

코드의 다른 측면으로 이동하면, svgCircle 요소와 그 형제 요소들은 다음 두 가지 <g> 요소 변형을 통해 표준 데카르트 좌표계에 주어집니다.


<g transform="translate(400, 400) scale(1, -1)">

즉, translate(400, 400)은 뷰포트 좌표계의 원점을, viewbox="0 0 800 800"을 통해 svg 요소에 주어진 800x800 보기 상자에 상대적인 점 (400, 400)으로 이동시킵니다. 그러면 scale(1, -1)이 사용자 좌표계의 x축 배율을 1(변화 없음)만큼, y축 배율을 -1만큼 변경하여 y축을 x축에 대해 대칭 이동하게 됩니다. 결과는 표준 데카르트 좌표계(원점이 800x800 뷰포트에 있음)가 됩니다.

샘플의 나머지(기타) 세부 사항은 Liquid SVG에서 내내 산발적으로 언급되는 방대한 설명을 통해 다루어집니다. 이 기법이 SVG 기반 비디오 게임에서 어떻게 사용되는지 보려면 고급 SVG 애니메이션의 예제 6을 참조하세요.

관련 항목

HTML5 그래픽
웹 페이지에 SVG를 추가하는 방법
고급 SVG 애니메이션
SVG(스케일러블 벡터 그래픽)

 

 

표시:
© 2014 Microsoft