关于d3.js:viewBox属性,其中设置了svg height和width属性

viewBox attribute with svg height and width attributes set

如果您查看此jsbin svg图像,它具有width和height属性以及一个viewBox属性集:

1
2
3
4
5
6
7
8
9
var width = width + margin.left + margin.right;
var height = height + margin.top + margin.bottom;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr('viewBox', '0 0 ' + width + ' ' + height)
  .append("g")
    .attr("transform","translate(" + margin.left +"," + margin.top +")");

然后,svg根本无法缩放。

但是,如果我随后注释掉width和height属性,那么它的确会像在此bin中那样缩放。

我对viewBox属性感到非常困惑,我在网上看到了很多都设置了width,height和viewBox属性的示例。 当存在width和height属性时,我认为viewBox属性无效。

我还对viewBox的width和height属性实际上对应于实际空间感到困惑。

文档说您正在指定自己的坐标系,但是我不明白这意味着什么,宽度和高度与文档的实际宽度和高度如何对应。


tl;dr: viewBox用于绘制SVG中的内容,widthheight告知要显示的大小。

viewBox定义了将SVG绘制到的画布和坐标系。如果显示viewBox="10 50 100 100",并且您想绘制一个覆盖图像左上四分之一的正方形,则将编写:

1
2
3
<svg viewBox="10 50 100 100" xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="50" width="50" height="50" />
</svg>

然后,当您要显示SVG时(例如嵌入到html页面中),宽度和高度告诉您显示它们的大小,就像图像标签一样:

1
2
3
4
  <svg width="250" height="250" viewBox="10 50 100 100"
       xmlns="http://www.w3.org/2000/svg">
    <rect x="10" y="50" width="50" height="50" />
  </svg>

如果将SVG保存为外部文件drawing.svg,则可以表示与

1
  <img src="drawing.svg" width="250" height="250" />

在这两种情况下,您绘制的正方形都将覆盖图像的左上四分之一,但是由于SVG是以250px的整体大小绘制的? 250px,正方形的边长为125px? 125px。

换句话说,如果viewBox中定义的宽度为a,并且元素上定义的宽度为b,则效果与将SVG内部的所有内容(水平)缩放为b / a相同。

(这显然提出了一个问题,当viewBox高度为c,元素高度为d并且比率d / c ≠ b / a不匹配时会发生什么?)就是preserveAspectRatio属性所描述的。)

形式上,widthheightviewBoxpreserveAspectRatio的每种组合都可以等效地写为transform属性。这里描述了算法。 (请注意,对于示例中此处使用的元素,xy属性必须始终为0。)