2014-06-26 85 views
4

我对SVG完全陌生,所以请耐心等待。我阅读了很多关于这个主题的文章,每个人都在指出像d3.js这样的解决方案,在我看来,这是对于我所拥有的简单任务来说很复杂的方法。笛卡尔坐标系的简单可缩放SVG图形

我需要使用笛卡尔坐标系制作一个图,其中(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> 

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

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

回答

8

您需要使用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> 

Demo here

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

<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>元素上使用百分比坐标,我们必须调整每个标签的变换。

这个问题的最佳解决办法可能是将您的所有标签放在<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> 

Demo here

+0

谢谢你,你的答案是非常有益的。我发现,如果网格和标签是静态的,它们不需要在笛卡尔的'g'范围内,它使代码更简单和更清晰。但还有一件事我想解决,但我不知道如何解决。我不需要保持宽高比。我希望图形填充页面(或父'div')并且灵活。用'viewport'可以实现吗? – Ulrik

+0

是的。使用''。 –

+0

几乎在那里(我试图自己做,但似乎我需要最后的和平拼图) - 有什么方法可以让标签保持比例? – Ulrik