SVG Transformation

Jakob Jenkov
Last update: 2021-03-10

It is possible to transform the shapes created in an SVG image. For instance move, scale and rotate the shapes. This is a handy way of displaying vertical or diagonal text.

Transformation Example

Here is a simple example:

<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">

    <rect x="50" y="50" height="110" width="110"
          style="stroke:#ff0000; fill: #ccccff"
          transform="translate(30) rotate(45 50 50)"
            >
    </rect>
    <text x="70" y="100"
          transform="translate(30) rotate(45 50 50)"
    >Hello World</text>
</svg>

Here is the resulting image:

Hello World

Notice the transform attribute of the <rect> and <text> elements. The transform attribute specifies what transformations to apply to the shapes. In this example a translation and rotation was applied. Both will be explained later in this text.

What Elements Can Be Transformed?

You can apply transformation to all SVG shapes. You can also apply transformation to the <g> element, thus effectively transforming a whole group of elements in one go. It is also possible to transform gradients and fill patterns.

Transformation Functions

SVG provides four transformation functions:

  • translate()
  • rotate()
  • scale()
  • skew()
  • matrix()

Each of these functions will be explained in more detail in the following sections.

Actually, the transformation functions do not transform the SVG shape themselves, but the underlying coordinate system of that shape. Thus, a shape with a width of 20 scaled up by a factor of 2, still has a width of 20 logically, even though it is displayed in double size.

Translate

The translate() function moves a shape. You pass the x and y value to the translate() function inside the parameters. Here is an example:

translate(50,25)

This example moves a shape 50 units along the x-axis and 25 units along the y-axis.

Here is an example showing two equally positioned and sized shapes with and without translation:

<rect x="20" y="20" width="50" height="50"
      style="fill: #cc3333"/>

<rect x="20" y="20" width="50" height="50"
      style="fill: #3333cc"
      transform="translate(75,25)" />

Here is the resulting image:

Notice how the second (blue) shape is moved 75 units along the x-axis and 25 units along the y-axis compared to the first (red) shape.

Rotate

The rotate() function rotates a shape around the point 0,0. Here is an example showing a rectangle (outline), and an equal rectangle (filled) after a rotation of 15 degrees:

<rect x="20" y="20" width="40" height="40"
      style="stroke: #3333cc; fill:none;"
        />

<rect x="20" y="20" width="40" height="40"
      style="fill: #3333cc"
      transform="rotate(15)"
        />

Here is the resulting image:

If you want to rotate around a different point than 0,0 then pass the x and y coordinates of that point to the transform function. Here is an example that shows a non-rotated rectangle (outline) and an equal rectangle (filled) rotated 15 degrees around its own center:

<rect x="20" y="20" width="40" height="40"
      style="stroke: #3333cc; fill:none;"
        />

<rect x="20" y="20" width="40" height="40"
      style="fill: #3333cc"
      transform="rotate(15, 40, 40)"
        />

Here is the resulting image:

All rotation is clock-wise with a number of degrees going from 0 to 360. If you want to rotate counter-clock-wise, pass a negative number of degrees to the rotate() function.

Scale

The scale() function scales a shape up or down in size. The scale() function scales both the shapes dimensions and its position coordinates. Thus, a rectangle positioned at 10,10 with a width of 20 and a height of 30, scaled by a factor of 2 will appear at 20,20 with a width of 40 and a height of 60.

The scale() function also scales the stroke width of a shape.

Here is an example that shows a rectangle (blue) positioned at 10,0 with a width of 20 and a height of 20, and an equal rectangle (black) which is scaled by a factor of 2:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="10" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="scale(2)" />

Here is the resulting image:

Notice how both the position and size of the rectangles are scaled.

You can scale a shape by a different factor on the x-axis and y-axis. You do so by providing both an x-scale and y-scale parameter to the scale() function, like this:

scale(2,3);

This example would scale the shape by a factor of 2 along the x-axis, and a factor of 3 along the y-axis. Here is an example of that:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="10" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="scale(2,3)" />

Here is the resulting image:

Notice how the stroke width of the scaled rectangle (black) is also scaled, and scaled differently on the x-axis and y-axis.

Scale as Mirror Function

You can use the scale() function as a mirror function by scaling by -1 along either the x-axis or y-axis. When you do, you have to first move (translate) the shape in the x or y direction, or the mirrored shape will appear outside the SVG canvas.

Here is an example:

<path d="M20,20 l20,20 l0,20 l-20,20 Z"
      style="stroke: #3333cc; fill:none;" />

<path d="M20,20 l20,20 l0,20 l-20,20 Z"
      style="stroke: #000000; fill:none;"
      transform="translate(100, 0) scale(-1, 1) " />

Here is the resulting image with a line drawn at x=100 (because the rectangle is translated 100 in the x direction).

The blue shape is the original. The black shape is the translated, scaled shape.

Skew

The skewX() and skewY() functions skew the x-axis and y-axis. Actually, the functions skew the given axis according to a certain angle specified in degrees.

Here are a few examples of rectangles shown with different skewX() values.

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(10)" />
<rect x="100" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(45)" />
<rect x="150" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(60)" />
    

Here is the resulting image:

As you can see, the skewX() function makes the vertical lines look like they were rotated by the given angle. Accordingly, the skewY() function makes the horizontal lines look like they were rotated by the given angle. Here are a few examples:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(60)" />
<rect x="100" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(45)" />
<rect x="150" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(10)" />

Matrix

It is possible to express transformations as a matrix too. The matrix looks like this:

a  c  e
b  d  f
0  0  1

Since only the first 6 values can be specified, you only provide 6 values to the matrix transformation function. Here is an example:

transform="matrix(a,b,c,d,e,f)"

The other transformation functions can be expressed as matrices. Here are some examples:

Translate

1  0  tx
0  1  ty
0  0   1

matrix(1,0,0,1,tx,ty)
Rotate

cos(a)   -sin(a)  0
sin(a)    cos(a)  0
     0        0   1

matrix( cos(a), sin(a),-sin(a),cos(a),0,0 )

Note: the values for cos(a) and sin(a) have to be precomputed before being inserted into the matrix. The parameter a is the angle to rotate.

Scale

sx  0  0
 0 sy  0
 0  0  1

matrix(sx,0,0,sy,0,0)

A skew transformation along the x-axis can be written as:

Skew

1  tan(a)  0
0       1  0
0       0  1

matrix(1,0,tan(a),1,0,0)

The tan(a) value has to be precomputed before being inserted into the matrix() function.

A skew transformation along the y-axis can be written as:

Skew

1       0  0
tan(a)  1  0
0       0  1

matrix(1,tan(a),0,1,0,0)

Here is an SVG matrix transformation example which mimics a simple translate function:

<rect x="20" y="20" width="50" height="50"
      style="fill: #cc3333"/>

<rect x="20" y="20" width="50" height="50"
      style="fill: #3333cc"
      transform="matrix(1,0,0,1,100,20)"
        />    

Here is the resulting image:

Notice how the right rectangle (blue) is translated compared to the left (red) rectangle.

Combining Transformations

It is possible to combine transformations. You do so by putting multiple transformation functions inside the transform attribute.

Here is an example that first translates (moves) and then rotates a rectangle. The example shows both the retangle (blue) before any transformation is applied, and after (black).

<rect x="50" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;"
        />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="translate(50,0) rotate(30)" />    

Here is the resulting image:

The Sequence of Transformations Matter

The sequence of transformations matter. The sequence the transformation functions are specified inside the transform attribute is the sequence they are applied to the shape.

Here is an example that illustrates the difference between translating first and then rotating, and rotating first and then translating the shape:

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; stroke-width: 2px; fill:none;"
        />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #3333cc; stroke-width: 2px;  fill:none;"
      transform="translate(100,0) rotate(45)" />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #cc3333; stroke-width: 2px;  fill:none;"
      transform="rotate(45) translate(100,0)" />    

Here is the resulting image:

The black rectangle has no transformation applied. The blue rectangle is first translated, then rotated. The red rectangle is first rotated, then translated.

Jakob Jenkov

Featured Videos

Java ConcurrentMap + ConcurrentHashMap

Java Generics

Java ForkJoinPool

P2P Networks Introduction

















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next