递归呈现SVG文件

4

是否有一个现成的渲染器可以智能地处理递归(即自引用)的SVG文件?

例如,来自这个问题的代码:

<svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="-50" cy="-50" r="30" style="fill:red" />
  <image x="10" y="20" width="80" height="80" xlink:href="recursion.svg" />
</svg>

在Firefox、Chrome或Inkscape中,<embed>标签的呈现存在问题,但似乎制作一个跟踪打开特定文件次数并在一定迭代次数后停止的渲染器并不难...

(如果没有现成的渲染器,我想自己编写一个,应该去哪里寻找?)


1
根据SVG规范,这样的循环依赖被视为错误,并且用户代理需要检测并跳出这样的循环。它们何时跳出未定义,请参见http://www.w3.org/TR/SVGTiny12/linking.html#circular-iri。 - Erik Dahlström
真糟糕。看来我得试着自己写了... - linkhyrule5
2个回答

5
您可以反复引用定义。虽然这不是无限递归,但比其他答案/评论中提到的嵌套方法简单得多。
请参见我发现的Dudley Storey的这些示例(示例1示例2)。

svg {
display: block;
width: 40%;
margin: 0 auto;
}
polygon, line { 
fill: none; stroke: #32679D; 
stroke-width: 5px; 
vector-effect: non-scaling-stroke;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 750 750">
<defs>
 <g id="hex" transform="rotate(30 375 375)">
  <polygon points="229.3,627.5 83.6,375.5 229.3,123.5 520.7,123.5 666.4,375.5 520.7,627.5" />
  <line x1="229.3" y1="123.5" x2="520.7" y2="627.5"/>
  <line x1="666" y1="375.5" x2="84" y2="375.5"/>
  <line x1="520.7" y1="123.5" x2="229.3" y2="627.5"/>
 </g>
</defs> 
<use xlink:href="#hex" />
<use xlink:href="#hex" transform="translate(470.75, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(470.75, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(91.75, 172) scale(.25)" /> 
<use xlink:href="#hex" transform="translate(91.75, 390.5) scale(.25)" />  
<use xlink:href="#hex" transform="translate(155, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(407.5, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 63.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 500) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 390.5) scale(.25)" />
</svg>


可以通过嵌套来变得更加复杂:

body {
margin: 0;
min-height: 100vh;
background: #fff;
}
svg {
display: block;
width: 100%;
min-height: 100vh;
}
polygon { 
fill: none; 
stroke: rgba(0,0,0,0.3); 
stroke-width: 3; 
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
 <pattern id="tesselation" patternUnits="userSpaceOnUse" width="562.6" height="325" patternTransform="scale(.75)">
 <g id="group">
  <polygon points="281.4,0 375.2, 162.5 281.4, 325 187, 161.5" id="base" />
  <g id="basetwist" >
   <use xlink:href="#base" transform="rotate(90 280 162.5) translate(116, 67) scale(.58)" id="base_level1" />
   <g id="diamond"> 
    <use xlink:href="#base" transform="translate(188.85, 108) scale(.33)" id="base_level2" />
    <g id="sidediamond">
     <use xlink:href="#base_level1" transform="translate(188.85, 108) scale(.33)" id="base_level3" />
      <use xlink:href="#base_level2" transform="translate(188.85, 108) scale(.33)" id="base_level4" />
       <use xlink:href="#base_level3" transform="translate(188.85, 108) scale(.33)" /> 
        <use xlink:href="#base_level4" transform="translate(188.85, 108) scale(.33)" />
    </g>
   </g>
   <use xlink:href="#sidediamond" transform="translate(62,0)" />
   <use xlink:href="#sidediamond" transform="translate(-62,0)" />
   <use xlink:href="#diamond" transform="translate(0,-107)" />
   <use xlink:href="#diamond" transform="translate(0, 107)" />
  </g>
 </g>
 <g id="tesselation">
  <use xlink:href="#group" />
  <use xlink:href="#group" transform="rotate(60 281 0)" />
  <use xlink:href="#group" transform="rotate(-60 281 0)" />
  <use xlink:href="#group" transform="rotate(-60 281 325)" />
  <use xlink:href="#group" transform="rotate(60 281 325)" />
  <g id="vert">
   <use xlink:href="#group" transform="translate(-282, -162)" />
   <use xlink:href="#group" transform="translate(-282, 162)" />
  </g>
  <use xlink:href="#vert" transform="translate(564, 0)" />
 </g>
 </pattern>
</defs>
<rect width="100%" height="100%" fill="url(#tesselation)" /> 
</svg>


编辑:他有博客文章描述了他是如何创建它们的:


顺便提一下,我无法正确显示代码块中第一个前导“列”中的制表符。如果有人能够解决这个问题,那么请编辑一下。 - mbomb007

0
为了保护用户的隐私,图像文件必须是自包含的。例如,如果您从图像标签引用一个SVG文件,并且该SVG文件本身包含图像,则必须将图像数据指定为data URL
您可以使用数据URL嵌套图像,嵌套深度可以任意设置,尽管这不是真正的递归,因为每次都需要提供完整的副本,而且您的数据URL将变得非常大。

对不起,我真的不理解这个答案。 - linkhyrule5
首先 - 我并不希望这被用于浏览器或HTML文档中,它是独立的。其次 - 你所说的数据URL是什么意思?这是否意味着一般情况下我不能轻松地嵌套复杂的图像文件? - linkhyrule5
这是SVG作为数据URL的示例 https://codepen.io/tigt/post/optimizing-svgs-in-data-uris您可以轻松地嵌套一个复杂的SVG,但不能轻松地进行多层嵌套。 - nHaskins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接