iframe内的SVG存在奇怪的不一致问题

时间:2014-11-01 22:59:32

标签: html html5 iframe svg webkit

我需要在iframe中渲染一些SVG,我需要使用srcdoc属性来完成它。出于某种原因,我正在做的事情导致SVG的某些属性无法正常显示。

在下面的屏幕截图中,iframe中的代码完全相同。

screenshot

以下是重现此内容的代码:

<svg height="150" width="300">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="100" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>

<br><br>

<iframe width="300" height="150" srcdoc='<svg height="150" width="300">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="100" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>'></iframe>

看起来它与linearGradients或url有关,以及它们在这种情况下的行为。

我最近在iframes和srcdocs方面遇到了一些其他问题,我在SO上发布了这个问题,得到了很好的回复:iframes rendering mysteriously differently from regular web pages? - 这有很多不一致的地方,但似乎与此无关特别是一个。

我正在使用Chrome / Webkit。

1 个答案:

答案 0 :(得分:8)

这似乎是iframe srcdoc文档如何解析内部目标链接的不幸结果。

使用srcdoc are supposed to be given特殊基本网址about:srcdoc创建的文档。

但是,在该文件中,the base URL for resolving external links or stylesheets is the parent document's URL。这可能意味着应该在父DOM而不是本地DOM中解析ID。但这显然没有发生,因为在您的原始示例中,父文档中存在具有该ID的有效渐变。现在,可能是跨源限制阻止来自单独文档的资源的结果,但我没有在控制台上收到相应的错误。

当您开始将目标片段用于其他事情时,事情变得非常糟糕(并且跨浏览器不一致)。

In this fiddle,作为下面的片段再现,我使用目标片段

  • 引用两个文档的渐变(一个用于笔划,一个用于填充;在Chrome(v38)或Firefox(v33)中都没有运气(IE根本不支持srcdoc)。

    < / LI>
  • 重复使用两个文件中的元素;如果<use>在FF中呈现,则Chrome会重复使用 local 椭圆,表示在这种情况下它会根据本地文档解析片段。

  • 定义超链接的目的地。在这种情况下,FF会给我一个POST错误,但Chrome成功导航到父文档中的目标 (请注意,:target样式已应用)。当然,这仅在父文档具有可导航URL(即,保存的JS小提琴,但不是堆栈片段)时才有效。

所有这些都是说,这是规范中的模糊性和实现中的不一致性的绝对混乱,我建议找一个替代方案,例如使用数据URI作为src的iframe中。请注意,这仍然不适用于IE(不支持iframe的数据URI),并且您需要对文档中的任何#%字符进行网址编码。

iframe srcdoc和网址碎片测试用例

ellipse:target {
    stroke:red;
}
<svg height="150" width="300">
  <defs>
    <linearGradient id="grad1" >
      <stop offset="0" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="1" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse id="parentEllipse" cx="100" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>

<br><br>

<iframe width="300" height="150" srcdoc='<svg height="150" width="300">
  <defs>
    <linearGradient id="grad2" >
      <stop offset="0" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="1" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
<a xlink:href="#parentEllipse">
  <ellipse id="ellipse" cx="100" cy="70" rx="85" ry="55" fill="url(#grad1) blue"  stroke="url(#grad2) green" stroke-width="10px" /></a>
  <use xlink:href="#ellipse" y="50"/>
  <use xlink:href="#parentEllipse" x="50" />
</svg>'></iframe>