SVG Coordinate Transformations

This topic covers SVG coordinate transformations that are associated with the getScreenCTM() method.

The subject of SVG coordinates and transformations is large. You can find basic information about this subject from the W3C SVG specification – specifically Coordinate Systems, Transformations and Units.

This topic covers a particularly pernicious issue associated with SVG coordinates – the mapping of a point in screen coordinates (technically, the initial viewport coordinate system) to the coordinate system associated with any given SVG element (technically, the current user coordinate system). For example, consider an SVG circle using a standard Cartesian coordinate system:

An SVG circle using a standard Cartesian coordinate system

Figure 1

In this example, we are interested in determining the position of the mouse relative to the circle’s coordinate system. Thus, we must map the mouse’s screen coordinates to the circle’s Cartesian coordinates as suggested by the following figure:

SVG circle with mouse coordinates mapped to Cartesian coordinates

Figure 2

In Figure 2, the mouse has a screen coordinate of (843, 270). When this point is mapped to the circle’s coordinate system, the mouse coordinate becomes (175, 175).

Note  

If you’re not familiar with matrices, matrix multiplication, or matrix inversion, consider reviewing one or more of the following before proceeding:

To describe the transformation in Figure 2 mathematically, it is helpful to start with a few definitions. From the W3C SVG specification, we have:

Transformation matrices define the mathematical mapping from one coordinate system into another. The current transformation matrix (CTM) defines the mapping from the user coordinate system into the viewport coordinate system using a 3x3 CTM matrix via the following equation:

Coordinate transform equation

where,

  • M is the current transformation matrix (CTM).
  • Homogenous vector is a homogenous vector that represents a point (x, y) in the user coordinate system. In Figure 2, this vector is Point (175, 175) in matrix form, which is equivalent to "circle point" (175, 175). Be aware that the "1" in Homogenous vector simply allows for matrix arithmetic and can essentially be ignored.
  • Primed homogenous vector is a homogenous vector that represents a point (x’, y’) in the viewport coordinate system. In Figure 2, this vector is Point (843, 270) in matrix form, which is equivalent to "screen point" (843, 270).

Fortunately, the CTM can be acquired in JavaScript by invoking the getScreenCTM() method. For example, if the circle in Figure 2 is named svgCircle, then var M = svgCircle.getScreenCTM() would return the appropriate matrix M to convert a circle point to a screen point using the previous equation. That is, if the current transformation matrix M for Figure 2 is:

CTM for figure 2

Then we can map circle coordinate (175, 175) to screen coordinate (843, 270) as follows:

Application of CTM

Which, after rounding, produces screen coordinate (843, 270).

The previous example shows how to transform a circle coordinate to a screen coordinate, but what about the inverse? That is, given a screen coordinate, what is the corresponding circle coordinate? To answer that question, we must solve Coordinate transform equation for x, y vector. This can be accomplished as follows:

Matrix equation solution

where,

  • M-1 is the inverse of the CTM matrix, which is approximately Inverse CTM for example for the above example. Because all allowed SVG coordinate transformations map a 2D space to another 2D space, M will always be invertible.
  • I represents the 3x3 identity matrix (recall that M-1 = I).

Thus using our derived equation Inverse matrix equation, we can map screen coordinate (843, 270) to its corresponding circle coordinate as follows:

Inverse matrix solution

Which, after rounding, produces circle coordinate (175, 175).

With this mathematical understanding in place, implementing Inverse matrix equation in JavaScript is relatively straightforward:


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

This function, given a screen point (of type SVGPoint) and some SVG object such as a circle, will map the screen point to the coordinate system associated with someSvgObject. If someSvgObject represents the circle of Figure 2, then:

  • var CTM = someSvgObject.getScreenCTM() gets the CTM associated with the current screen and circle size.
  • CTM.inverse() inverts the CTM matrix, giving us M-1 in the prior equation.
  • screenPoint.matrixTransform( CTM.inverse() ) multiplies M-1 and the given screen coordinate Screen coordinate matrix (that is, screenPoint) to produce the required circle coordinate Circile coordinate matrix.

To view the full sample associated with Figure 2, click Liquid SVG. To view the source code associated with this sample, use the view source feature of your browser. For example, in Windows Internet Explorer, right-click the webpage and choose View source. Make sure you have the source code available while reading the remainder of this document.

Be aware that as you change the size of the browser window, the circle size adjusts accordingly. This liquid layout is the result of the following percent-based values:


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

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

and


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

Moving to a different aspect of the code, the svgCircle element, as well as its sibling elements, are given a standard Cartesian coordinate system via the following two <g> element transforms:


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

That is, translate(400, 400) moves the origin of the viewport’s coordinate system to the point (400, 400) relative to the 800x800 view box imposed on the svg element via viewbox="0 0 800 800". The scale(1, -1) transform then scales the user coordinate system’s x-axis by 1 (no change) and the y-axis by -1, which has the effect of flipping the y-axis about the x-axis. The result is a standard Cartesian coordinate system (whose origin occurs in the middle of the 800x800 viewport).

The remaining (minor) details of the sample are covered via the copious comments sprinkled throughout Liquid SVG. To see how this technique is used in an SVG-based video game, see Example 6 of Advanced SVG Animation.

Related topics

HTML5 Graphics
How to Add SVG to a Webpage
Advanced SVG Animation
Scalable Vector Graphics (SVG)

 

 

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.