SVG Tutorial - View Box

Background

In this post, we will explain the view box feature in SVG. It can be used to scale the image.

First, let's define our canvas. We will define a 800 * 400 div and a 600 * 300 svg. The background color of div is pink and the background color of the svg is blue. Note that the svg will be put in the middle of the div.

We will also put a rectangle and circle on the svg:

1
2
<rect x="50" y="50" width="100" height="60" stroke="#5628ed" fill="none"/>
<circle cx="400" cy="200" r="20"  stroke="#5628ed" fill="none"/>


The size of the svg file is the size of the canvas. It's the area for drawing. In our case, our canvas is 600 * 300. When we specify an element in a svg file, the coordinate system used is the coordinate system of the canvas.

The view box, as the name suggests, is the area of view. By default, it coincides with the canvas, meaning that we can see all element on the canvas.

This setup of terminology can be confusing because we can draw elements outside of the canvas and we just cannot see it. For example, if we add another rectangle, we will not see it.

1
<rect x="800" y="200" width="100" height="60" stroke="red" fill="none"/>


Display Area and View Area

If we think more about it, the concept of a canvas in SVG does not make a lot of sense because there is no limit to the coordinates and we can draw anywhere we want. So what is exactly the size in the svg tag?

To some extent, it's the display area. It defines the size of an area for display purposes using the svg coordinate system. Therefore, in our case, the 600 * 300 svg means we will have a 600 * 300 area in the svg coordinate system to display our view. By default, the initial view box is (0, 0, widthOfSvg, heightOfSvg) and this is the reason why the image is not scaled.

In the previous image, we added a rectangle (x=800, y=200, width=100, height=60). It's not displayed because it's not in the view area (view box). To change the view area (view box), we can set the viewBox attribute. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div style="width=800;height=400;background-color:#ffc7c7;text-align:center;">

<svg version="1.1"
viewBox="700 0 800 400",
width="600" height="300"
style="background-color:#c7e9ff;"
xmlns="http://www.w3.org/2000/svg">

<rect x="50" y="50" width="100" height="60" stroke="#5628ed" fill="none"/>
<circle cx="400" cy="200" r="20"  stroke="#5628ed" fill="none"/>
<rect x="800" y="200" width="100" height="60" stroke="red" fill="none"/>
</svg>

</div>


This time, the original rectangle and the circle disappear because they are not in the view area anymore.

Scale the Image

So how do we scale a svg image? If the display area has the same size as the view area, then the scale is 1 or there is no scaling effect. If the display area is larger than the view area, then the image will be amplified because we can display more details. If the display area is smaller than the view area, then the image is scaled down because some of the details of the image are lost.

Going back to our initial example:

1
2
3
4
5
6
7
8
9
10
11
12
13
<div style="width=800;height=400;background-color:#ffc7c7;text-align:center;">

<svg version="1.1"
width="600" height="300"
style="background-color:#c7e9ff;"
xmlns="http://www.w3.org/2000/svg">

<rect x="50" y="50" width="100" height="60" stroke="#5628ed" fill="none"/>
<circle cx="400" cy="200" r="20"  stroke="#5628ed" fill="none"/>
<rect x="800" y="200" width="100" height="60" stroke="red" fill="none"/>
</svg>

</div>


If we set the viewBox to "40 40 200 100", the view area is 200 * 100 and the display area is 600 * 300. In this case, the display area is larger than the view area and the image is enlarged.

If we set the viewBox to "0 0 1000 500", the view area is 1000 * 500 and the display area is still 600 * 300. In this case, the display area is smaller than the view area. We expect to see the image is reduced (kind of compressed):

Aspect Ratio

If the aspect ratio of the display area and the one of the view area are different, then the portion seen in the display area is distorted. We can control the adjustment of the aspect ratio by setting preserveAspectRatio attribute.

Impact of Transform

Let's do an experiment with the transform:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div style="width=800;height=400;background-color:#ffc7c7;text-align:center;">

<svg version="1.1"
width="600" height="300"
transform="scale(1, -1)"
style="background-color:#c7e9ff;"
xmlns="http://www.w3.org/2000/svg">

<rect x="50" y="50" width="100" height="60" stroke="blue" fill="blue"/>
<rect x="50" y="150" width="100" height="60" stroke="green" fill="green"/>
</svg>

</div>



As we can see the position of the blue and green rectangles are reversed because now they are presented in Cartesian coordinate system. Now suppose we only want to view the blue rectangle. Intuitively, because the y-axis is flipped, we would expect that the viewBox in Cartesian coordinate system is defined by the lower left point of the rectangle. So let's set viewBox to "0 -180 600 300". The number -180 is calculated using the formula 120 - 300.

Here is the code and the result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div style="width=800;height=400;background-color:#ffc7c7;text-align:center;">

<svg version="1.1"
width="600" height="300"
viewBox="0 -180 600 300"
transform="scale(1, -1)"
style="background-color:#c7e9ff;"
xmlns="http://www.w3.org/2000/svg">

<rect x="50" y="50" width="100" height="60" stroke="blue" fill="blue"/>
<rect x="50" y="150" width="100" height="60" stroke="green" fill="green"/>
</svg>

</div>


To make it more clear. The y coordinate of center horizontal line of green rectangle is 150 + 60 / 2 = 180. If we want to see half of the green rectangle, the max y coordinate of the view area in the Cartesian coordinate should be 180. For the height of the view area is 300, the min y coordinate of the view area is 180 - 300 = -120. In order to see half green rectangle, we should set viewBox to "0 -120 600 300". Here is the result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div style="width=800;height=400;background-color:#ffc7c7;text-align:center;">

<svg version="1.1"
width="600" height="300"
viewBox="0 -120 600 300"
transform="scale(1, -1)"
style="background-color:#c7e9ff;"
xmlns="http://www.w3.org/2000/svg">

<rect x="50" y="50" width="100" height="60" stroke="blue" fill="blue"/>
<rect x="50" y="150" width="100" height="60" stroke="green" fill="green"/>
</svg>

</div>


----- END -----

Welcome to join reddit self-learning community.

Want some fun stuff?