D3js-SVG简单初步

D3最擅长于生成和操纵SVG图像来进行可视化。绘制div或其它原生HTML元素也是可以的,但是考虑到不同浏览器之间总会存在一些标准上的差异,使用SVG会更可靠更稳定,也会更快一些。

类似于Illustrator的矢量绘图软件可以生成SVG文件,但是我们这里讨论的是如何用代码来生成。

SVG元素

可扩展矢量图形(Scalable Vector Graphics, SVG)是一种基于文本的图像格式。每个SVG图像都由类似于HTML的标签代码来定义。SVG代码可以直接用于HTML文档中。每个网页浏览器都是支持SVG的(除了IE8及之前的版本)。SVG是基于XML的,因此你会发现没有结束标签的元素必须是自封闭的。比如

<element></element>   <!-- Uses closing tag -->
<element/>            <!-- Self-closing tag -->

在你开始画之前,你必须先生成一个初始的SVG元素。将此元素视为一个画布,你将要在此画布上大展身手(从这个意义看,SVG的这个元素类似于HTML的canvas元素)。即使在一个最小的示例中,你最好也指定一下widthheight。如果你没有指定宽度和高度,它会占用svg所在元素中的尽可能多的空间。

<svg width="500" height="50">
</svg>

下面给出效果图

没看到? 尝试在空白位置点击右键,再选择”Inspect Element”,你的浏览器应该得到类似于下面的结果

注意,这里确实有一个svg元素,而它刚好就占用了宽为500像素高为50像素的一个区域。只不过,空白的图像确实没什么好看的。

还需注意的是,浏览器默认像素为数值单位。我们用的是50050,而无需用500px50px。当然你也可以显式地指定px,或任意其它浏览器支持的单位,比如emptincmmm

简单形状

svg标签中,你可以使用大量的图形元素,包括rectcircleellipselinetextpath

如果你熟悉计算机图形编程,你会了解通常的基于像素的坐标系统的原点0,0位于绘制区域的左上角。增加x值会导致右移,增加y值会导致下移。

0,0100,20200,40

rect元素会画出一个矩形。可以用xy来指定它的左上角的位置,而用widthheight指定其大小。下面的这个矩形填充了我们的整个SVG画布。

<rect x="0" y="0" width="500" height="50"/>

circle元素会画出一个圆。可以用cxcy来指定圆心位置,而用r来指定其半径。下面的这个圆位于我们的500个像素宽的画布的中心,所以它的cx值为250。

<circle cx="250" cy="25" r="25"/>

ellipse元素是类似的,只不过它在每个轴上的半径可以不一样。因此,半径r变成了rxry

<ellipse cx="250" cy="25" rx="100" ry="25"/>

line元素用来画一条线段。它使用x1y1指定线段的一个端点位置,而用x2y2来指定另外一端的位置。笔画stroke的颜色也必须指定,不然就混在背景里看不见了。

<line x1="0" y1="0" x2="500" y2="50" stroke="black"/>

text用于渲染文本。它使用x指定文本左边界的位置,用y来指定基线(baseline)的垂直坐标。

<text x="250" y="25">Easy-peasy</text>
Easy-peasy

除非显式地指定(后面马上会详细介绍如何指定文本样式),text会继承父元素中的CSS指定的字体样式。注意,上面例子中的文本与周围的段落的格式是保持一致的。我们可以用下面的代码修改其格式。

<text x="250" y="25" font-family="sans-serif"
     font-size="25" fill="gray">Easy-peasy</text>
Easy-peasy

另外,需要提醒的是,任意到达SVG画布边界的图形元素都会被裁剪掉。所以,使用text时要小心,确保里面的字符不要被裁掉。如果将基线坐标(y)修改为50,也就是SVG的高度,你就能体会到这一点了。

<text x="250" y="50" font-family="sans-serif"
     font-size="25" fill="gray">Easy-peasy</text>
Easy-peasy

path用于绘制更复杂的形状(比如地图中的国境线),将来我会单独介绍。但现在,我们只讨论简单形状。

SVG元素的样式

SVG的默认样式是黑色填充而不画线。如果你想修改样式,你需要将样式应用到元素上。常用的SVG属性有:

  • fill — 一个颜色值。和CSS一样,颜色可以有几种指定方式
    • 颜色名称。比如orange
    • 十六进制数。比如#3388aa#38a
    • RGB值。比如rgb(10,150,20)
    • RGB值加上不透明度。rgba(10,150,20,0.5)
  • stroke — 也是一个颜色值,即画线时的颜色
  • stroke-width — 一个数值(一般是以像素为单位)
  • opacity — 0到1之间的一个数值,0表示完全透明,1表示完全不透明

通过text,你可以使用下面这些属性,它们含义和CSS是保持一致的。

  • font-family
  • font-size

和CSS一样,为SVG元素指定样式也有两种方式:直接作为元素属性,或使用CSS样式规则。下面是直接将样式属性应用于circle的代码:

<circle cx="25" cy="25" r="22"
 fill="yellow" stroke="orange" stroke-width="5"/>

当然,我们可以不直接用这些样式属性,而是为circle指定一个样式类(就像为HTML元素指定类一样)。

<circle cx="25" cy="25" r="22" class="pumpkin"/>

然后,把fillstrokestroke-width这些规则放到一个CSS样式中,这样就构成了一个新类。

.pumpkin {
    fill: yellow;
    stroke: orange;
    stroke-width: 5;
 }

使用CSS方法有一些明显的好处:

  • 样式只需定义一次,然后应用到多个元素上
  • 一般,CSS代码比元素属性代码更易懂
  • CSS方法更易控制,从而让设计更高效

不过,使用CSS来应用SVG样式还是会让一些人心里不舒服。因为fillstrokestroke-width其实都不是CSS属性(最接近的CSS属性是background-colorborder)。如果你想将SVG专用的规则标记出来,你可以在选择器中加上svg关键字。

svg .pumpkin {
    /* ... */
}

图层和绘制顺序

SVG中没有”层”和深度的概念。SVG也不支持CSS的z-index属性。所以,形状都只能是x/y平面上的二维图形。

但是,多个形状之间又常常会出现重叠。

<rect x="0" y="0" width="30" height="30" fill="purple"/>
<rect x="20" y="5" width="30" height="30" fill="blue"/>
<rect x="40" y="10" width="30" height="30" fill="green"/>
<rect x="60" y="15" width="30" height="30" fill="yellow"/>
<rect x="80" y="20" width="30" height="30" fill="red"/>

元素的编码顺序决定了它们的深度顺序。紫色的矩形最先出现在代码中,因此它被首先画出来。然后蓝色矩形覆盖了紫色矩形,之后是绿色,依此类推。

将SVG视为画布就很好理解了。先画的总是被后画的给掩盖,因而后画的形状表现为最上面。

因此,如果有些形状不能被遮挡,则绘制顺序就很重要了。比如,坐标轴和散点图上的标签。坐标轴和标签总是应该出现在SVG代码的最后面,这样才能保证它们始终出现在其它元素的上面。

透明度

如果在可视化中出现重叠,而你又想让被遮挡的元素可见,或者你想强调一些元素而弱化其它一些,那么透明度就有用武之地了。

使用透明度有两种方法:使用带不透明度的RGB,或单独设置不透明度opacity

你可以在任意需要颜色的地方使用rgba(),比如fill,或stroke.rgba()都接受3个0至255之间的颜色值(分别表示红绿蓝)和1个0.0至1.0的不透明度值。

<circle cx="25" cy="25" r="20" fill="rgba(128, 0, 128, 1.0)"/>
<circle cx="50" cy="25" r="20" fill="rgba(0, 0, 255, 0.75)"/>
<circle cx="75" cy="25" r="20" fill="rgba(0, 255, 0, 0.5)"/>
<circle cx="100" cy="25" r="20" fill="rgba(255, 255, 0, 0.25)"/>
<circle cx="125" cy="25" r="20" fill="rgba(255, 0, 0, 0.1)"/>

注意,在用rgba()时,fillstroke的不透明度是独立的。下面这个例子中,圆在填充时fill的不透明度是75%,而stroke的不透明度是25%。

<circle cx="25" cy="25" r="20" fill="rgba(128, 0, 128, 1.0)"/>
<circle cx="50" cy="25" r="20" fill="rgba(0, 0, 255, 0.75)"/>
<circle cx="75" cy="25" r="20" fill="rgba(0, 255, 0, 0.5)"/>
<circle cx="100" cy="25" r="20" fill="rgba(255, 255, 0, 0.25)"/>
<circle cx="125" cy="25" r="20" fill="rgba(255, 0, 0, 0.1)"/>

如果要为整个元素设置不透明度,可以使用opacity属性。下面的例子是完全不透明的圆。

同样是这些圆,设置不同的opacity之后,结果就会变化。

<circle cx="25" cy="25" r="20" fill="purple" 
        stroke="green" stroke-width="10"
        opacity="0.9"/>
<circle cx="65" cy="25" r="20" fill="green"
        stroke="blue" stroke-width="10"
        opacity="0.5"/>
<circle cx="105" cy="25" r="20" fill="yellow"
        stroke="red" stroke-width="10"
        opacity="0.1"/>

你也可以在使用rgba()的同时再设置元素的opacity。这时,不透明度会相乘。下面例子中的圆对于fillstroke使用同样的RGBA值,第一个圆没有设置opacity,而后两个设置了。

注意,第3个圆的opacity为0.2,即20%。而它的紫色填充已经有了不透明值0.75(或75%)。因此,紫色区域最终的不透明度为0.2乘以0.75,结果为0.15,或15%。

来源:http://www.pkuwwt.tk/d3-tutorial-cn/the-svg-primer.html

你可能感兴趣的:(svg,D3JS)