6

我对 SVG 完全陌生,所以请多多包涵。我阅读了很多关于这个主题的文章,每个人都指向像 d3.js 这样的解决方案,在我看来,这对于我所拥有的简单任务来说是一种复杂的方式。

我需要用笛卡尔坐标系制作一个图,其中 (0,0) 位于左下角。它需要具有以百分比表示的宽度、高度和数据,因此所有内容都随页面缩放。

所以,这是我的代码(为简单起见,图中只有一部分):

<style>
 .grid {stroke: white; stroke-width: 1; stroke-dasharray: 1 2}
 .label{font-family: courier new; fill: white; font-size: 14px}
 .data {stroke: white; stroke-width: 1}
</style>

<svg width="100%" height="100%">
 <g class="x grid">
  <line x1="0%"   x2="0%"   y1="80%" y2="100%"></line>
  <line x1="10%"  x2="10%"  y1="80%" y2="100%"></line>
  <line x1="20%"  x2="20%"  y1="80%" y2="100%"></line>
 </g>
 <g class="y grid">
  <line x1="0%" x2="20%" y1="80%"  y2="80%" ></line>
  <line x1="0%" x2="20%" y1="90%"  y2="90%" ></line>
  <line x1="0%" x2="20%" y1="100%" y2="100%"></line>
 </g>
 <g class="x label">
  <text x="10%"  y="100%"> 1 minute </text>
  <text x="20%"  y="100%"> 2 minutes</text>
 </g>
 <g class="y label">
  <text x="0%" y="80%"> 20% </text>
  <text x="0%" y="90%"> 10% </text>
 </g>
 <g class="data">
  <line x1="0%"  x2="10%"  y1="85%"  y2="92%"  ></line>
  <line x1="10%" x2="20%"  y1="92%"  y2="88%"  ></line>
 </g>
</svg>

我想使用polygonandpath作为数据,所以我可以填充曲线下方的区域,但它不喜欢将百分比作为值。有人建议使用viewbox将百分比转换为像素,然后使用像素,但这会弄乱我的网格。我还希望在左下角有 (0,0),这样我的 CGI 就不必对它需要显示的所有点进行数学运算。我试过transform="translate(0,100) scale(1,-1)"了,但这不适用于百分比。我也尝试过transform="rotate(270)",但是当你减小窗口宽度时,图形高度会降低......

那么,有人可以在这里启动我,并帮助我建立一个流畅的、可调整大小的图表,原点位于左下角,曲线下方的彩色区域?

4

1 回答 1

11

您需要使用 viewBox,因为正如您所发现的,变换组件不采用百分比。使用 viewBox,您仍然可以使用百分比作为坐标。但是,您需要选择一个长宽比与最终图形相似的 viewBox。否则页面上的对象可能会被压扁或拉伸。

<svg width="100%" height="100%" viewBox="0 0 500 500">
  <g id="cartesian" transform="translate(0,500) scale(1,-1)">
    <g class="data">
      <line x1="0%"  y1="75%" x2="50%"  y2="40%" ></line>
      <line x1="50%" y1="40%" x2="100%" y2="60%"></line>
    </g>
  </g>
</svg>

不幸的是,翻转坐标系有副作用。如果翻转包括文本在内的所有对象,如果我们添加一些,您可以看到:

<svg width="100%" height="100%" viewBox="0 0 500 500">
  <g id="cartesian" transform="translate(0,500) scale(1,-1)">
    <g class="data">
      <line x1="0%"  y1="75%" x2="50%"  y2="40%" ></line>
      <line x1="50%" y1="40%" x2="100%" y2="60%"></line>
    </g>
    <g class="y label">
      <text x="0%" y="50%"> 10% </text>
      <text x="0%" y="90%"> 20% </text>
    </g>
  </g>
</svg>

演示在这里

所以你需要通过再次以正确的方式翻转文本来解决这个问题。

<svg width="100%" height="100%" viewBox="0 0 500 500">
  <g id="cartesian" transform="translate(0,500) scale(1,-1)">
    <g class="data">
      <line x1="0%"  y1="75%" x2="50%"  y2="40%" ></line>
      <line x1="50%" y1="40%" x2="100%" y2="60%"></line>
    </g>
    <g class="y label">
      <text x="0%" y="50%" font-size="16"
            transform="translate(0,500) scale(1,-1)"> 10% </text>
      <text x="0%" y="90%" font-size="16"
            transform="translate(0,900) scale(1,-1)"> 20% </text>
    </g>
  </g>
</svg>

不幸的是,正如您所看到的,这会破坏我们使用百分比坐标干净地定位标签的能力。如果我们想在<text>元素上使用百分比坐标,我们必须调整每个标签的变换。

这个问题的最佳解决方案可能是将所有标签放在 a<defs>中并使用<use>. 这样我们就可以以正确的方式翻转它们用百分比坐标定位它们。

<svg width="100%" height="100%" viewBox="0 0 500 500">
  <defs>
    <text id="label1" font-size="16" transform="scale(1,-1)"> 10% </text>
    <text id="label2" font-size="16" transform="scale(1,-1)"> 20% </text>
  </defs>
  <g id="cartesian" transform="translate(0,500) scale(1,-1)">
    <g class="data">
      <line x1="0%"  y1="75%" x2="50%"  y2="40%" ></line>
      <line x1="50%" y1="40%" x2="100%" y2="60%"></line>
    </g>
    <g class="y label">
        <use xlink:href="#label1" x="0%" y="50%"/>
        <use xlink:href="#label2" x="0%" y="90%"/>
    </g>
  </g>
</svg>

演示在这里

于 2014-06-27T06:27:39.980 回答