The SVG attribute viewBox
appears to be inconsistent. It seems it doesn't scale all SVG graphics primitives the same way. Here's a sample SVG file that has a rectangle, a circle
, a polyline
, and a polygon
. The rectangle has been properly scaled and almost filled the viewPort (which has a width
of 500 and a height
of 500).
Please see the SVG code and image it produced below. As you will notice the polyline
, polygon
, and circle
did not scale to fill the view port. They do (consistently) occupy the top-left quarter of the view port though (moved but retaining the original size). Can anyone please throw some light on what's going on with this? I will greatly appreciate your feedback.
<?xml version='1.0' encoding='utf-8'?>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
height='499' width='501' viewBox='100 100 200 200'>
<g stroke='BLACK' stroke-width='5' fill='none'>
<rect x='105' y='105' width='193' height='193'/>
<polygon points="150,100 200,200 100,200" style="stroke:purple" />
<polyline points='115,180 155,127 180,180' stroke='red'/>
<circle cx='150' cy='150' r='50' stroke='green'/>
</g>
</svg>
Short answer:
The SVG
attribute viewBox
on the sample code does scale all SVG graphics the same way; so the smaller object representations are actually smaller objects.
Explanation:
It's useful to look at he viewBox
documentation to better understand the calculations. Let's try to go through you sample code step-by-step:
SVG
viewport dimensions are set to 501 by 499 (width
by height
)viewBox
attributes are set as
min-x
and min-y
, which will act like shifting the position of the viewport before its container top and left positions (which in the image it seems like irrelevant, since you also shifted all the coordinates by 100; see my note below)width
and height
, which will represent 100% of the viewport size (in this case ~500px
); in other words, the 200 value in any children will be mapped (scaled) into ~500px
rect
has 193 as width
and height
, which is nearly 200, this makes it occupy almost all of the ~500px by 500px
viewport areacircle
has r='50'
which would fit an imaginary outer square of 100 by 100; 100 is 50% of 200, so it is scaled to ~250px by ~250px (250 = 50% of 500); that is why the circle seems to use 1/4 of the area NOTE:
I found it was easier to understand the final results if there was no shift on the viewport and on the positioning coordinates. So, removing 100 from viewBox
> min-x
and min-y
(step 2.1 above) and from all the positioning attributes would make this code easier to understand:
<?xml version='1.0' encoding='utf-8'?>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
height='499' width='501' viewBox='0 0 200 200'>
<g stroke='BLACK' stroke-width='5' fill='none'>
<rect x='5' y='5' width='193' height='193'/>
<polygon points="50,0 100,100 0,100" style="stroke:purple" />
<polyline points='15,80 55,27 80,80' stroke='red'/>
<circle cx='50' cy='50' r='50' stroke='green'/>
</g>
</svg>