Embed SVG in SVG?

前端 未结 6 550
無奈伤痛
無奈伤痛 2020-11-27 11:00

I have an SVG document, and I would like to include an external svg image within it, i.e. something like:



        
                      
相关标签:
6条回答
  • 2020-11-27 11:30

    Note xlink:href has been deprecated, just use href instead, e.g.

    <svg viewBox="0 0 512 512">
      <image width="512" height="512" href="external.svg"/>
    </svg>
    

    viewBox, width and height values (in this answer) are simply for illustration purpose, adjust the layout accordingly (read more).

    Since <image> shares similar spec as <img>, meaning it doesn't support SVG styling, as mentioned in Christiaan's answer. For example, if I have the following css line that set the svg shape color to be the same as the font color,

    svg {
      fill: currentColor;
    }
    

    The above style wouldn't apply if <image> is used. For that, you need to use <use>, as shown in Nick's answer.

    Note id="layer1" and href="OTHERFILE.svg#layer1" values in his answer are mandatory.

    Meaning you have to add the id attribute to the external svg file, so you need to host the (modified) external svg file by yourself (your website) or somewhere else. The resulting external svg file looks like this (notice where I put the id):

    <svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
      <path d="..."/>
    </svg>
    

    The value of id can be anything, I use "logo" in this example.

    To embed that svg,

    <svg viewBox="0 0 512 512">
      <use href="edited-external.svg#logo"/>
    </svg>
    

    If you use the above svg as inline in your html, you don't need xmlns attribute (at least what I know from svgo).

    0 讨论(0)
  • 2020-11-27 11:31

    It is worth mentioning that when you embed SVGs into another SVG with:

    <image x="10" y="20" width="80" height="80" xlink:href="image.svg" />
    

    then the embedded SVG takes a rectangular shape with given dimensions.

    That is to say, if your embedded SVG is a circle or some shape other than a square, then it becomes a square with transparency. Therefore, mouse events get trapped into that embeded square and do not reach the parent SVG. Watch out for that.

    A better approach is using a pattern. To fill a shape, either a circle, a square or even a path.

    <defs>
     <pattern id="pat" x="0" y="0" width="500" height="500" patternUnits="userSpaceOnUse">
       <image x="0" y="0" width="500" height="500" xlink:href="images/mysvg.svg"></image>
     </pattern>
    </defs>
    

    Then use the pattern like this:

    <circle cx="0" cy="0" r="250" fill="url(#pat)"></circle>
    

    Now your mouse events do not get stuck into transparent image squares!

    0 讨论(0)
  • 2020-11-27 11:33

    I found that using the <image> tag gave a low-quality render of the embedded file. However the following technique worked (to embed an SVG file inside an SVG file - not necessarily for rendering on an HTML page):

    • Edit the SVG file in a text editor.

    • Find the end of the metadata:

      </metadata>
        <g
         id="layer1"
         inkscape:groupmode="layer"
         inkscape:label="Layer 1">
      
    • Insert this line after that group tag:

      <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
      
    • In this case we are including OTHERFILE.svg into the file, and all of layer1 (the first and default layer).

    • Save this and then open the file in Inkscape.

    This technique is useful for having a standard background or logo on every page. By putting it first in the file it will be rendered first (and thus at the bottom). You could also lock it by adding this attribute:

    sodipodi:insensitive="true" 
    

    In other words:

    <use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />
    
    0 讨论(0)
  • 2020-11-27 11:34

    Use the image element and reference your SVG file. For fun, save the following as recursion.svg:

    <svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
         xmlns="http://www.w3.org/2000/svg">
      <circle cx="-50" cy="-50" r="30" style="fill:red" />
      <image x="10" y="20" width="80" height="80" href="recursion.svg" />
    </svg>
    
    0 讨论(0)
  • 2020-11-27 11:39

    I needed to embed a SVG in my SVG but also change its color and apply transforms.

    Only Firefox supports the "transform" attribute on the nested svg elements. Changing the color of <image> is also not possible. So a combination of both was needed.

    What I ended up doing was the following

    <svg>
      <image x="0" y="0" xlink:href="data:image/svg+xml;base64,[base64 of nested svg]"></image>
    </svg>
    

    This works on at least Firefox, Chrome and Inkscape.

    This behaves the same as the child svg in the parent svg answer with the exception that you can now apply transforms on it.

    0 讨论(0)
  • 2020-11-27 11:41

    Or you can actually embed child svg in parent svg like this:

    <svg>
        <g>
            <svg>
                ...
            </svg>
        </g>
    </svg>
    

    demo:
    http://hitokun-s.github.io/old/demo/path-between-two-svg.html

    0 讨论(0)
提交回复
热议问题