在 SVG 中嵌入 SVG?

Posted

技术标签:

【中文标题】在 SVG 中嵌入 SVG?【英文标题】:Embed SVG in SVG? 【发布时间】:2011-07-23 23:53:16 【问题描述】:

我有一个 SVG 文档,我想在其中包含一个外部 svg 图像,例如:

<object data="logo.svgz"   x="200" y="400"/>

("object" 只是一个示例 - 外部文档将是 SVG 而不是 xhtml)。

有什么想法吗?这甚至可能吗?还是将 logo.svg xml 简单地添加到我的外部 SVG 文档中对我来说是最好的选择?

【问题讨论】:

【参考方案1】:

使用 image 元素并引用您的 SVG 文件。为了好玩,将以下内容另存为recursion.svg

<svg   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"   href="recursion.svg" />
</svg>

【讨论】:

谢谢,由于某种原因,我的谷歌搜索直到我发布这个问题后才起作用。我注意到要渲染的图像必须存在宽度和高度。 一个有趣的观察:最新版本的 Firefox、Chrome 和 Safari 都只显示了使用上述方法的一级递归(两个点)。但是,如果您将上述内容另存为“a.svg”并将图像更改为“b.svg”,然后将其保存为“b.svg”并且图像引用“a.svg”,那么Firefox 将显示附加每次重新加载交替文件时的递归级别。每次加载文件时,它似乎都会缓存结果,更深一层。 @IanStormTaylor SVG 元素本身没有样式属性;而是 SVG 元素内的项目具有样式。但是,当使用 SVG 中的 &lt;image&gt;(或 HTML 中的 &lt;img&gt;&lt;embed&gt;)来引用 SVG 文件时,您无法访问底层 DOM。因此,不,您不能在被 &lt;image&gt; 引用的 SVG 元素中设置元素样式。 @proteneer &lt;image xlink:href="data:image/svg+xml;utf8,&amp;lt;svg …&amp;gt;… &amp;lt;/svg&amp;gt;" /&gt;。 (如果您使用 javascript 设置 href 属性,则无需转义 &lt; 等字符。) xlink:href is deprecated,现在你应该只使用href。您能否更新您的答案以包含该内容?【参考方案2】:

或者您实际上可以像这样将子 svg 嵌入父 svg:

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

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

【讨论】:

@toshi 你有另一个回答的例子吗?我正在尝试但未能实施您的建议。我的“外部”SVG 设置了一个圆圈和渐变。我的内部 SVG 是一个对象。独立,内部 SVG 按预期工作。但内部 SVG 不会显示在我对您建议的实施中。因此,我请求查看另一个示例。 +1 用于提及独立的替代方案。这种嵌入式 svg 的定位/大小如何工作? 我想补充一点,你可以为这个 元素添加变换:平移、旋转等。这样你可以动态地重新定位元素 例如,要移动一个元素,你可以这样写:...【参考方案3】:

值得一提的是,当您将 SVG 嵌入到另一个 SVG 中时:

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

然后嵌入的 SVG 采用具有给定尺寸的 矩形 形状。

也就是说,如果您嵌入的 SVG 是圆形或正方形以外的其他形状,那么它就会变成具有透明度的正方形。因此,鼠标事件会被困在嵌入的正方形中,并且不会到达父 SVG。请注意这一点。

更好的方法是使用模式。填充形状,可以是圆形、正方形,甚至是路径。

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

然后使用这样的模式:

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

现在您的鼠标事件不会卡在透明图像方块中了!

【讨论】:

那个填充图案很完美,谢谢。对于较小的插入或较小的视图框,编码人员可能希望以同等方式减小所有宽度和高度。【参考方案4】:

我发现使用&lt;image&gt; 标签会导致嵌入文件的渲染质量很低。然而,以下技术有效(将 SVG 文件嵌入到 SVG 文件中 - 不一定用于在 HTML 页面上呈现):

在文本编辑器中编辑 SVG 文件。

找到元数据的结尾:

</metadata>
  <g
   id="layer1"
   inkscape:groupmode="layer"
   inkscape:label="Layer 1">

在该组标签之后插入这一行:

<use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />

在这种情况下,我们将 OTHERFILE.svg 包含到文件中,以及 layer1 的所有内容(第一层和默认层)。

保存此文件,然后在 Inkscape 中打开文件。

此技术对于在每个页面上都有标准背景或徽标很有用。通过将它放在文件中,它将首先呈现(因此在底部)。你也可以通过添加这个属性来锁定它:

sodipodi:insensitive="true" 

换句话说:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />

【讨论】:

@WilliamEntriken “外部文件”是什么意思?我描述的方法使用了一个外部文件,即包含其他内容的文件。【参考方案5】:

注意xlink:href 一直是deprecated,只需使用href 代替,例如

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

viewBoxwidthheight 值(在此答案中)仅用于说明目的,请相应调整布局 (read more)。

由于&lt;image&gt; shares similar spec 为&lt;img&gt;,这意味着它不支持SVG 样式,如Christiaan's answer 中所述。例如,如果我有以下 css 行将 svg 形状颜色设置为与字体颜色相同,

svg 
  fill: currentColor;

如果使用&lt;image&gt;,上述样式将不适用。为此,您需要使用&lt;use&gt;,如Nick's answer所示。

注意他回答中的id="layer1"href="OTHERFILE.svg#layer1" 值是强制

意味着您必须将 id 属性添加到外部 svg 文件中,因此您需要自己(您的网站)或其他地方托管(修改后的)外部 svg 文件。生成的外部 svg 文件如下所示(注意我把 id 放在哪里):

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

id的值可以是任何值,我在这个例子中使用了“logo”。

要嵌入该 svg,

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

如果您在 html 中使用上述 svg 作为内联,则不需要 xmlns 属性(至少我从 svgo 知道的)。

【讨论】:

viewBox 不是强制性的,如果您省略它,您将获得不同的布局,但在某些情况下这可能是您想要的。 Safari 才刚刚开始支持 href。【参考方案6】:

我需要在我的 SVG 中嵌入一个 SVG,但还需要更改它的颜色并应用变换。

只有 Firefox 支持嵌套 svg 元素的“transform”属性。也无法更改 的颜色。因此需要将两者结合起来。

我最终做的是以下

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

这至少适用于 Firefox、Chrome 和 Inkscape。

这与父 svg 答案中的子 svg 的行为相同,但您现在可以对其应用转换。

【讨论】:

【参考方案7】:

使用 SVG &lt;use&gt; 标签嵌入额外的 SVG 怎么样?

【讨论】:

【参考方案8】:

非常简单

<image x="120" y="720"   href="assets/img/image.svg" />

【讨论】:

以上是关于在 SVG 中嵌入 SVG?的主要内容,如果未能解决你的问题,请参考以下文章

在 PDF 中嵌入 SVG(使用 JS 将 SVG 导出为 PDF)

如何检查嵌入的 SVG 文档是不是加载到 html 页面中?

SVG 嵌入图像仅在浏览器中显示

在 HTML 中嵌入外部 SVG 以进行 JavaScript 操作

在使用canvas api在浏览器中将svg转换为png时,svg中的嵌入图像在Safari中随机空白

嵌入 SVG 时 wkhtmltopdf 失败