SVG Coordinates, Viewport, viewBox

, , …,
Want to master JavaScript in a week? Buy Xah JavaScript Tutorial.

This page is a basic tutorial on SVG “viewBox” attribute. If you are new to SVG, see SVG Tutorial: Basic Examples.

viewport

viewport is a rectangular region within the current canvas onto which graphics elements are to be rendered.

The dimension of viewport can be set via width and height attributes.

Here's a circle.

Here's the code:

<svg width="100" height="100">
<circle cx="50" cy="50" r="50"
style="stroke:green; fill:none" />
</svg>

Note the values of the “width” & “height” attributes.

the width & height makes up the area called viewport.

The top left corner of the viewport has coordinate {0,0}. That is, x = 0 and y = 0. this point is called the origin.

Changing the width or height does not change the coordinate.

<svg width="200" height="100">
<circle cx="50" cy="50" r="50"
style="stroke:green; fill:none" />
</svg>

Another example:

<svg width="70" height="100">
<circle cx="50" cy="50" r="50"
style="stroke:green; fill:none" />
</svg>

The dimension of viewport can be set via CSS too.

<svg style="width:100px; height:100px">
<circle cx="50" cy="50" r="50"
style="stroke:green; fill:none" />
</svg>

viewBox Attribute

You can use the “viewBox” attribute to control the coordinate origin and the coordinate's x range and y range.

here's the syntax of the viewBox:

<svg width="…" height="…" viewBox="min-x min-y width height" >

Any drawing outside of the {width, height} will not be shown.

Here's some examples.

Shifting Coordinates

Here, we shift the coordinate, so the drawing area's top left corner is {30,0}.

Here's a circle centered on {30,0} with radius 20.

<svg width="100" height="100" viewBox="30 0 100 100">
<circle cx="30" cy="0" r="20" style="stroke:green; fill:blue" />
</svg>

Change Visible Range

Here, we set the viewBox's x & y ranges to be both 50.

<svg width="100" height="100" viewBox="0 0 50 50">
<circle cx="0" cy="0" r="50"
style="stroke:green; fill:none" />
</svg>

The viewBox will always be scaled uniformly to fit in the viewport (which may leave empty spaces), and will be centered. Aspect ratio is preserved by default.

Here's the tech detail. Suppose, viewport width and height is {pX,pY} and viewBox width and height is {bX, bY}. Now, there's 2 ratios: pX/bX and pY/bY. Whichever is smaller will be the scaling factor.

Controlling viewport/viewBox Mapping: “preserveAspectRatio” attribute

The “preserveAspectRatio” attribute can be used to control the exact scaling & position of viewBox in viewport.

First, observe that when viewport & viewBox have different width & height, there are these cases:

when the viewBox is scaled uniformly, there's also alignment issue. Namely, allign to {top, middle, bottom} in x-dimension, and same for y-dimension.

SVG provides a very convenient attribute “preserveAspectRatio”. You just tell it which of the above case you want, and you don't have to do any of the math for scaling & positioning.

here's the syntax:

preserveAspectRatio="none"

the above means don't preserve aspect ratio. Scale each dimention to fit.

to preserve aspect ratio, use this:

preserveAspectRatio="alignment spec meet or slice"

The possible values for alignment spec is one of:

the meet or slice is either meet or slice.

Nested SVG

You can nest a SVG inside a SVG. This is useful when you want to have a area for graph and another area for caption, legends, etc.

For example, suppose you want to plot a graph y=x^2. The range you want to plot is {x, 0, 10} and {y, 0, 10}. So, you can create a view box with height & width of 10. But, you also need a area for the graph's caption.

Normally, you need to scale & position all your drawing coordinates to leave room for caption. But you can have a nested SVG tag inside the main SVG viewbox. In the inner SVG, you can just specify a viewbox dimension & position for the coordinate for your plot. This way, you don't have to otherwise recompute or transfor your drawing's coordinates.

The syntax for the nested SVG is just 2 extra attribute, x & y: <svg x="…" y="…">. The x & y specifies where your inner SVG is positioned.

Here's a example:

<svg width="100" height="100">
  <svg x="20" y="20" width="80" height="80" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" style="fill:green; stroke:blue; stroke-width:5" />
  </svg>
</svg>

In the above example, the SVG view box is same as view port, with side length of 100. It has a inner SVG, with side length of 80, with origin at {20,20}. The inner SVG has a view port with side length of 100. (so, you don't have to rescale your points.) It draws a square of length 100.

Reference

Coordinate Systems, Transformations and Units – SVG 1.1 (Second Edition)

blog comments powered by Disqus