D3.js 使用嵌套 svg 缩放会破坏 Internet Explorer 中的视口

D3.js zoom with nested svg breaks viewport in Internet Explorer

我正在使用 d3.js 动态设置嵌套 svg,即嵌套在封闭 svg 中的内部 svg。 d3.behavior.zoom() 侦听外部 svg 上的缩放事件并进行所需的转换。

除了 Internet Explorer (IE 11) 似乎在涉及内部 svg 的转换方面存在问题外,一切正常。 Firefox 和 Chrome 都按照预期的方式将内部 svg 剪裁到外部 svg 的视口。然而,在 Internet Explorer 中,放大会正确应用转换,但似乎会忽略封闭 svg 的尺寸。内部 svg 的内容最终将显示在外部 svg 之外和其他 body 元素之上。外部 svg 的视口似乎对内部 svg 没有裁剪效果。

我已经设置了一个 JSFiddle 来演示该行为。

var zoom = d3.behavior.zoom()
    .on("zoom", function () {
        container.attr("transform",
            "translate(" + d3.event.translate + ") " +
            "scale(" + d3.event.scale + ")");
    });

var container = d3.select("body")
                    .append("svg")
                      .attr("id", "svgcontainer")
                      .attr("width", 300)
                      .attr("height", 300)
                      .style("background-color", "#aaaaee")
                      .call(zoom)
                    .append("g");

var svg = container.append("svg")
                     .attr("width", 200)
                     .attr("height", 200)
                     .attr("x", 50)
                     .attr("y", 50);

svg.append("svg:circle")
     .style("fill", "none")
     .style("stroke", "red")
     .style("stroke-width", "2px")
     .attr("cx", 100)
     .attr("cy", 100)
     .attr("r", 50);

我错过了什么吗?有任何跨浏览器的解决方法吗?

很抱歉这个问题在您第一次发布时没有得到足够的重视:它实际上是一个简单的修复。只需将外部 SVG 上的 overflow 属性 设置为 hidden.

那么,为什么您的代码在其他浏览器上能按预期运行?

这是因为他们默认设置了这个属性。 CSS中overflow的初始值为visible,但SVG specs要求任何可以采用viewBox属性的元素在overflow:hidden中浏览器的默认样式表,except 用于根 SVG 元素。其他浏览器将此异常解释为仅适用于作为 .svg 文档根的 <svg> 元素。 Internet Explorer 还适用于将 HTML 文档中的顶级内联 SVG 视为根(因此具有 overflow: visible)。

以下代码片段演示了不同的行为。它在内嵌 SVG 内的嵌套 SVG 内使用圆圈。圆对于嵌套的 SVG 来说太大了,所以如果嵌套的 SVG 上隐藏了溢出(所有浏览器默认情况下都是如此),圆将被裁剪成正方形。嵌套的 SVG 发生偏移,部分位于外部 SVG 之外。如果溢出隐藏在外部 SVG 上,则嵌套 SVG 将被裁剪为矩形;如果可以看到溢出,您会看到方块伸出框架。

第一个 SVG 在外部 SVG 上使用默认溢出(对于 IE 不同),而其他 SVG 明确设置 overflow: hiddenoverflow: visible.

svg {
    border: solid gray;
    height: 100px;
    width: 100px;
    margin: 50px;
}
circle {
    fill: royalBlue;
}
<svg>
    <svg x="-50" y="-50" width="100" height="100" >
        <circle r="100" cx="50" cy="50"/>
    </svg>
</svg>
<svg style="overflow: hidden">
    <svg x="-50" y="-50" width="100" height="100" >
        <circle r="100" cx="50" cy="50"/>
    </svg>
</svg>
<svg style="overflow: visible">
    <svg x="-50" y="-50" width="100" height="100" >
        <circle r="100" cx="50" cy="50"/>
    </svg>
</svg>

可能应该为 SVG 2 or in the SVG integration spec 澄清溢出行为。 Firefox 和 Blink/Webkit 浏览器之间也存在差异,关于内联 SVG 上的填充是否被视为 "overflow"。