I'm developing a program that generates svg files based on choices the user makes. One of these choises is to include another svg file centered on a specific point in the first one. The second file has an unknown aspect ratio and size, but it should be scaled to a specific max size either as height or width, and should be centered on one specific point. The method I use now is to have a G tag that contains the SVG tag of the included image, and perform a transform on the G tag to scale and translate. Is there any way to perform the scale to get a specific size without knowning the size of the image? And is there any way to have the translated coordinates to apply to the center of the image instead of the upper left corner? I am very new to SVG, so it might be that I'm going about this the wrong way. Is there perhaps a better way to get the same results?
3 Answers
I guess you want to first have the other SVG file hidden, call .getBBox() in JavaScript do some simple calculations, set the appropriate parameters, unhide it
I understand what you mean, or least I think that. There's no better idea across my mind to do that instead of grouping. For me <g>
is the best way to manipulate with one fragment of SVG document. But in my opinion consider the <rect>
element as container for your visual data. Maybe then <g>
would not be necessary, depends on your coding requirements.
If you need to put only simple SVG image you can do it like:
<image id="yourSVGImage" xlink:href="yourImg.svg"
x="24px" y="50px" width="527px" height="328px"
preserveAspectRatio="XMinYMin meet"/>
If you express "width" and "height" in fixed units (such as pixels) you will achieve what I'm thinking you need. Also "preserveAspectRatio" is there to take a look at this attribute if you need it.

- 3,167
- 6
- 35
- 50
Edit: this answer stil requires you to know the size of the inner SVG. The most decoupled way is to use the getBBox() method on the browser side, probably using visibility
or display
to prevent users from seeing the unscaled graphics. The jsFiddle example is updated to use this method.
For scaling, use the viewBox attribute. From W3C's documentation:
It is often desirable to specify that a given set of graphics stretch to fit a particular container element. The ‘viewBox’ attribute provides this capability.
All elements that establish a new viewport (see elements that establish viewports), ... have attribute ‘viewBox’. The value of the ‘viewBox’ attribute is a list of four numbers
<min-x>
,<min-y>
,<width>
and<height>
, ... 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’.Example ViewBox illustrates the use of the ‘viewBox’ attribute on the outermost svg element to specify that the SVG content should stretch to fit bounds of the viewport.
The example above specifies preserveAspectRadio
as none
, so the embedded SVG stretches to fit the container SVG exactly. The default value of preserveAspectRadio
, which is xMidYMid meet
, should fit your needs. This attribute allows you a fine-grained control over how to scale and position the enclosed graphics.
Once you've scaled the inner SVG to a known size with viewBox
, centering should be a matter of simple calculation and using the transform
attribute properly. Here a stripped down example from http://jsfiddle.net/ento/hPuBY/ :
<g transform="translate(125, 125)">
<!-- inner SVG is scaled to fit 150x150 -->
<svg width="150" height="150" viewBox="0 0 1500 1000">
<!-- coordinate system inside the SVG is 0x0 <> 1500x1000 -->
<rect width="1500" height="1000" />
<text x="750" y="550" font-size="150">
Embedded SVG
</text>
</svg>
</g>