Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG viewBox: Exact order of translation and scaling

Tags:

svg

I am struggling to understand exactly how min-x and min-y on viewBox works, from a technical standpoint (without metaphors).

Two helpful resources I have spent quite a lot of time on:

  • SVG 1.1 (official specification) - 7.7 The ‘viewBox’ attribute
  • Understanding SVG Coordinate Systems and Transformations (Part 1) - by Sara Soueidan

According to the SVG 1.1 specification:

The value of the ‘viewBox’ attribute is a list of four numbers , , and , separated by whitespace and/or a comma, which specify a rectangle in user space which should be mapped to the bounds of the viewport established by the given element, taking into account attribute ‘preserveAspectRatio’.

And:

The effect of the ‘viewBox’ attribute is that the user agent automatically supplies the appropriate transformation matrix to map the specified rectangle in user space to the bounds of a designated region (often, the viewport).

And:

(Note: in some cases the user agent will need to supply a translate transformation in addition to a scale transformation. For example, on an outermost svg element, a translate transformation will be needed if the ‘viewBox’ attributes specifies values other than zero for or .)

So, my expectation was that defining a viewBox is the same as:

  1. First scaling the viewbox, so it fills the viewport (assuming same aspect ratio on viewport and viewBox)
  2. Then translating the viewBox, so it is placed in the viewport according to min-x and min-y viewBox attributes.

If we look at Sara's two examples, starting here, that is not what seems to be happening.

In her first example (<svg width="800" height="600" viewbox="100 100 200 150">...</svg>), it looks like:

  1. viewBox is placed according to min-x / min-y in viewport
  2. viewBox is scaled to same size as viewport
  3. viewBox origin is translated (moved) to coincide with viewport origin

In her second example however (<svg width="800" height="600" viewbox="-100 -100 400 300">...</svg>), it looks like a completely different order:

  1. viewBox is scaled to same size as viewport
  2. viewBox origin is translated (moved) somehow in the opposite direction of what viewBox min-x min-y indicates. It does not coincide with viewport origin - This is different from the first example

Thus, I recognize that I do not fully understand it, because technically it should work the same way in both cases.

Finally, in Sara's examples, I do not understand why the blue coordinate system (user coordinate system) does not itself move, to (100, 100) or (-100, -100) in viewport coordinate system. I thought viewBox was supposed to translate and scale the user coordinate system?


EDIT:

According to this SO answer, min-x and min-y does indeed follow my first set of steps. The viewBox origin is placed in the viewport according to min-x and min-y, and then translated so its origin is on top of viewport origin. It is then (before or after) scaled to fill viewport.

If that is correct, I have a hard time understanding why the blue user coordinate system in Sara's examples do not always end up with its origin on top of viewport origin. After all, viewBox should modify the user coordinate system.

like image 610
Magnus Avatar asked Dec 02 '18 16:12

Magnus


1 Answers

The offset of the origin of the coordinates viewBox on the x-axis (min-x=70px)

<svg width="400" height="400" viewBox="70px, 0, 400px, 400px">

enter image description here

In the figure, the origin of user coordinates shifts to the right by 70px, thereby shifting the entire rectangular viewing areaviewBox (400 x 400px)to the right along the horizontal axis.

When this happens, the image of the SVG document fragment that is under the viewBox is captured and then the viewBox viewing area with the captured fragment is back aligned with the fixed user viewport area with the origin (0,0) in the upper left corner.

The coordinates of the figures are recalculated with the last shift of 70px to the left. Formally it turns out that in the fixed viewing area of the viewport when applying the viewBox the fragment of the SVG document has shifted to the left.

enter image description here

Live Demo

The offset of the origin of the viewBox along two axes

min-x=70px, min-y="70px"

<svg width="400" height="400" viewBox="70px, 70px, 400px, 400px">

For clarity, add another red rectangle at the bottom of the picture - 6

enter image description here

After transferring the origin to the viewBox, a rectangular 400 × 400 px SVG document fragment with a width and height count from the origin (70.70) gets into the viewBox.

Image capture occurs. Next, the origin of the viewBox (70,70) is combined with the origin of the viewport (0,0). The coordinates of the figures are recalculated.

enter image description here

Therefore, red rectangles 5 and 6 become fully visible. Everything that does not fall into this area is cut off. For example, part of the areas of colored circles 1,2 and 4.

Live Demo

Zoom using viewBox

The scale of the SVG document fragment depends on the aspect ratio: viewport andviewBox

If viewport /viewBox = 1, then the scale will be 1

If viewport /viewBox different from one, the scale will change in the direction of increase or decrease.

enter image description here

How does the increase in scale explains the figure below

One pixel viewBox stretches to two pixelsviewport

enter image description here

Live Demo

Zoom out svg image 1: 2

<svg width="400" height="400" version="1.1" viewBox="0 0 800 800">

viewport / viewBox = 1/2

enter image description here

The viewBox captures a rectangular fragment 800 x 800 px, that is, the entire scope of the SVG viewport 400 x 400 px and an additional 400px each on the right and bottom of the viewport.

enter image description here

That is two pixels of the viewBox are compressed into one pixel of the viewport. Therefore the SVG image is reduced by half.

Live Demo

like image 163
Alexandr_TT Avatar answered Sep 22 '22 06:09

Alexandr_TT