解读SVG

如果在互联网网站的设计中使用过图形,一定听说过可伸缩矢量图形(SVG),甚至下载一个插件在浏览器中浏览SVG图片。对于SVG,我们首先需要了解也是最重要的一点是,它不是一种专有的形式。相反,它是一种描述二维图形的XML语言,是由W3C提出的一项开放性标准。
SVG是一种在XML中定义二维图形的语言,它包括3种类型的图形对象:适量图形(例如,包括直线、曲线在内的图形边)、图像和文本。图形对象可以与已经绘制好的对象结合,其特性包括多重转换、裁减、α变换、滤镜效果和模块对象。
  SVG图像具有交互性和动态性。动画可以通过定义(例如在SVG内容中嵌入SVG动画元素)或脚本制作。
  在这篇文章中,我将阐述使用SVG图形所需要的所有基础知识。

安装

  我们希望制作的招贴画的大小为信纸大小的一半儿,这一规模将在<svg>后进行说明,还应该包含<title>和<desc>元素,SVG的显示程序使用<title>标志显示工具提示,搜索引擎需要用到<desc>标记提供的信息。此外,我们创建的文档也很方便视力不大好的用户使用。

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20001102//EN"
"http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd">
<svg width="21cm" height="13.5cm">
<title>MegaMall Handbill</title>
<desc>
Handbill for the fictitious MegaMall
</desc>
<!-- graphic specifications go here -->
</svg>

  在指定width和height后,我们实际上就建立了一个显示图形的显示区,单位可以使用em、ex、px、pt、pc、cm、mm,如果不指定单位,则缺省的单位是像素点。

  所有其他物品的测量数字的单位与width和height所使用的单位相同。在我们的招贴画中,我们将设定width=21cm和height=13.5cm。为了必须在坐标中使用小数点,我们将建立一个viewBox。viewBox建立与viewport边界相重合的用户自己的坐标系统,如果与显示区不成比例,可以对图像进行缩放,只有在preserveAspectRatio被设置成none(这不是缺省设置)时才会进行缩放。在下面的说明中,我们把每厘米设定为10个单位。
<svg id="body" width="21cm" height="13.5cm"
viewBox="0 0 210 135">


  添加图像元素

我们首先从添加一个边框为红色、内部为淡蓝色的长方形开始:

<svg id="body" width="21cm" height="13.5cm"
viewBox="0 0 210 135">
<title>Example 1</title>
<desc>
Rectangle with red border and light blue interior.
</desc>
<rect x="10" y="20" width="150" height="70"
fill="#eeeeff" stroke="red" stroke-width="1" />
</svg>

  通过设置长方形的X、Y座标及其宽度和高度,我们就定义了一个长方形。在定义坐标时,正的X值是指向坐标原点的右方,正的Y座标是指向原点的下方。

  在本例中,我们还分别定义了填充颜色、线条颜色和线条的宽度,当然也可以通过与CSS类似的方式设置所有属性。

  下面是只有实际大小的一半儿的结果:


 图形变换

  下面,我们在招贴画中添加一个灰色的阴影长方形。我们希望新添加的长方形在原来的长方形的右、下方三个单位。在这里我们不使用增加X、Y座标的方法,而采取让原来的图形进行变换的方式来完成这一任务,应该在二个座标方面上对图形进行3个单位的变换。下面是这个变换的SVG脚本和得到的结果:

<svg id="body" width="21cm" height="13.5cm"
viewBox="0 0 210 135">
<title>Example 2</title>
<desc>
Rectangle with red border and light blue interior,
with (intended) gray shadow rectangle.
</desc>
<rect x="10" y="20" width="150" height="70"
fill="#eeeeff" stroke="red" stroke-width="1" />

<rect x="10" y="20" width="150" height="70"
transform="translate(3, 3)"
fill="#999999" stroke="#999999" stroke-width="1" />
</svg>

也许我们没有太在意,但这次图形变换表明了SVG的一种基本规则:如果源文件中对象B的定义在对象A之后,则它显示在对象A的上面。只要颠倒二个长方形在源文件中的顺序,就可以得到我们需要的结果。

<svg id="body" width="21cm" height="13.5cm"
viewBox="0 0 210 135">
<title>Example 3</title>
<desc>
Rectangle with red border and light blue interior,
with gray shadow rectangle.
</desc>
<rect x="10" y="20" width="150" height="70"
transform="translate(3, 3)"
fill="#999999" stroke="#999999" stroke-width="1" />

<rect x="10" y="20" width="150" height="70"
fill="#eeeeff" stroke="red" stroke-width="1" />
</svg>

图形重用

  我们将在长方形的上、下方显示绿色的圆环。如果仔细观察,就会发现这些圆环实际只是一个圆环的多次重复。把一个圆环放在<defs>元素内部,就表示这个图形对象在以后还会重复使用,但并不想让它立即显示出来。因此,应该在</desc>标记之后立即添加它。

1 <defs>
2 <polyline id="loop"
3 points=
4 1.00, 0.00 0.93, 0.16
5 0.72, 0.26 0.43, 0.25
6 0.13, 0.11 -0.11, -0.13
7 -0.25, -0.43 -0.26, -0.72
8 -0.16, -0.93 0.00, -1.00
9 0.16, -0.93 0.26, -0.72
10 0.25, -0.43 0.11, -0.13
11 -0.13, 0.11 -0.43, 0.25
12 -0.72, 0.26 -0.93, 0.16
13 -1.00, 0.00"
14 transform="scale(5, 5)"
15 stroke="green" stroke-width="0.1" fill="none" />
16 </defs>

 第1行
  开始定义区域
 第2行
  polyline保留字定义一组互相连接的直线段,id给予选定的对象一个唯一的名字,以后可以通过它调用该图像对象。
 第3-13行
  points属性列出直线段中每一个点的座标对。这些点恰好在极坐标方程r = 2cos(a)(a的取值范围在0°-180°之间)上,这也是这些点的坐标在X、Y轴上都在-1至1之间的原因。可以用逗号或空格分隔各个点。
 第14行
  为使圆环足够大,以便我们能够看清楚,我们使用缩放变换将各个点的X、Y座标都乘以5。需要注意的是,这个对象中所有点的座标都被扩大了5倍。
 第15行
  将该线段的颜色设置成绿色,注意应该将笔划的宽度设置成0.1,因为它也会被扩大5倍。
在画完长方形后,用<use>元素就可以使用前面定义的对象,把它放在招贴画中合适的地方,<use>元素中的xlink:href是引用的资源的URI,其产生的结果如下所示,下面是代码:

<rect x="10" y="20" width="150" height="70"
fill="#eeeeff" stroke="red" stroke-width="1" />
<use xlink:href="#loop" transform="translate(20,100)"/>

组合对象

  使用<g>元素可以将几个对象组合在一起,用它可以制作长方形下面的圆环。我们可以对任何对象进行组合,可以把组放在任意希望的深度。在本例中,我们将<use>元素中指定的以前定义的圆环组合在一起。在<defs>元素中添加下面的代码:

<g id="multiloop">
<use xlink:href="#loop"/>
<use xlink:href="#loop" transform="translate(10, 0)"/>
<use xlink:href="#loop" transform="translate(20, 0)"/>
<use xlink:href="#loop" transform="translate(30, 0)"/>
<use xlink:href="#loop" transform="translate(40, 0)"/>
<use xlink:href="#loop" transform="translate(50, 0)"/>
<use xlink:href="#loop" transform="translate(60, 0)"/>
<use xlink:href="#loop" transform="translate(70, 0)"/>
<use xlink:href="#loop" transform="translate(80, 0)"/>
<use xlink:href="#loop" transform="translate(90, 0)"/>
<use xlink:href="#loop" transform="translate(100, 0)"/>
<use xlink:href="#loop" transform="translate(110, 0)"/>
<use xlink:href="#loop" transform="translate(120, 0)"/>
</g>

  然后,用调用多个圆环的<use>元素替换原来的<use>元素,代码如下所示:

<use xlink:href="#multiloop" transform="translate(20, 100)"/>


对象的旋转

  为在招贴画顶端产生颠倒的圆环,我们需要使用旋转变换。旋转有二种格式:

 第一种旋转方式:
  语法格式:rotate(angle)

   效果:以坐标原点(0,0)为中心、以度为单位将对象旋转指定的角度。

 第二种旋转方式:
  语法格式:rotate(angle, cx, cy)

   效果:以(cx, cy)为中心将对象旋转angle指定的角度。

  在许多情况下,使用第二种旋转方式更方便,尤其是一个对象不是以原点为中心对称时,象一个单一的圆环就是这种情况。多个圆环的中心点是(60,0)。

<!-- loops at bottom -->
<use xlink:href="#multiloop" transform="translate(20, 100)"/>

<!-- loops at top -->
<use xlink:href="#multiloop"
transform="translate(20, 10) rotate(180, 60, 0)"/>

需要注意的是,在旋转变换中使用的角度是以度为单位的,正的数值表明是顺时针方向,0度表示正东,90度表示正南等

添加其他的图形和路径

  在招贴画中添加圆形物品是相当简单的,使用<circle>就可以完成这个任务,cx参数表示圆心的x座标,参数cy表示圆心的y座标,r表示半径。我们将在<defs>小节中添加<circle>元素,而不指定缩放和颜色信息,这就使我们以后可以随意改变颜色。

<circle id="bullet" cx="0" cy="0" r="1.5"/>

  其他的SVG图形对象如<rect>、<polyline>和<polygon>都代表一个比较复杂的路径对象。一个路径表示一个图形的轮廓,我们可以把一个星形物品看作为一个 <polygon>元素,但我们还是更喜欢将它称作一个路径。

<path>元素的主要属性是d参数,它表示路径数据,路径数据包含路径命令字符和座标信息。下表列出了一些重要的路径命令字符:

  字符含义
 M 移到动下一个(x,y)点
 L 在当前点和下一个(x,y)点之间划线
 A 利用描述X和Y轴上半径、X轴的旋转、方向和范围的大小以及椭圆的X、Y座标的终点等信息划一个椭圆。
 Z 结束一个路径,光标返回最近的一个Moveto点。

  SVG提供了数种捷径来使得描述一个路径所需的空间最少。如果需要使用重复的命令字符时(例如,一系列的直线和圆),就无需重复这些字符,还可以删除一些非必要的空格。下面的三个路径描述了同一个平行四边形:

<path d="M 5,3 L 10,3 L 7,6 L 2,6 Z"/>
<path d="M 5,3 L 10,3 7,6 2,6 Z"/>
<path d="M5 3L10 3 7 6 2 6Z"/>

大写字符表示绝对座标,小写字符表示相对座标。

下面是一个没有经过压缩的星形图形的路径的代码:

<path id="star"
d="M -0.951,-0.309L 0.951,-0.309,-0.588, 0.809,0.000,-1.000,0.588, 0.809
Z"transform="scale(3,3)" stroke="none" />

下面是在主SVG代码中对上面的各段代码进行调用的代码,及其结果:

<use xlink:href="#bullet" fill="#990000" transform="translate(5, 120)"/>
<use xlink:href="#star" fill="#009900" transform="translate(10, 120)"/>
<use xlink:href="#star" fill="#990099" transform="translate(180, 120)"/>
<use xlink:href="#bullet" fill="#000099" transform="translate(185, 120)"/>

SVG还提供了产生立方体和二次贝兹尔曲线的字符命令,但它们已经超出了本文讨论的范围。相机的路径使用了二次曲线。下面是相机路径规格的结果:

添加文本

  <text>是一个容器元素,欲显示的文本放在开始和结束的标志之间,最重要的属性是文本的的X和Y座标、字型、字号、填充颜色。
  如果要改变文本中一、二个单词的属性,应该使用<tspan>元素而不是用多个<text>元素来表达欲显示的文本,相机上的文本是被组合在一起的,因此无需对每个<text>元素都重复使用字型和字号属性:

<text font-family="sans-serif" font-size="10pt" fill="black"
x="18" y="123">Cameras cost
<tspan fill="#990000" font-style="italic"
text-decoration="underline">less</tspan>
at <tspan font-family="serif">MegaMart</tspan>!
</text>

<g font-family="sans-serif" font-size="6pt" fill="black">
<text x="54" y="59">
<tspan fill="red">S</tspan><tspan
fill="green">V</tspan><tspan fill="blue">G</tspan>
</text>
<text x="53" y="66">Cam</text>
</g>

我们还要在招贴画的右面添加一些带斑点、旋转的文本。下面是源代码:

<text font-family="serif" font-size="12pt" fill="black"
x="0" y="0"
transform="rotate(-90) translate(-100, 180) scale(1.5, 1)">
MegaMart
</text>

 滤镜效果

  最后一个任务是利用SVG的<filter>元素将黄光放到旋转的文字后面。<filter>元素可以使我们对一个图像对象运用一个或多个滤镜(即图像操作),与改变图像大小、形状、方向的变形操作不同,滤镜通常只影响一个图像对象的视觉效果。与其他的图像处理软件类似,SVG也有使图像变模糊、改变图像颜色饱和度、在其上添加其他图像或与其他图像重叠、产生倾斜或浮雕效果和光源效果的滤镜。
  由于将二次使用“MegaMart”,因此将它放入<defs>节中:

<text id="megaText" fill="black" x="0" y="0"
font-family="serif" font-size="12pt">
MegaMart
</text>

  要使黑色文字产生黄光,必须使图像的边缘变得模糊,将其灰度级变为黄色,其代码如下,为了叙述方便,我们在每行代码前面加了行号:

1 <filter id="glowShadowFilter">
2 <feGaussianBlur stdDeviation="0.7 0.7"/>
3 <feColorMatrix
4 type="matrix"
5 values=
6 "1 0 0 0 0
7 0 1 0 0 0
8 0 0 0 0 0
9 0 0 0 1 0"/>
10 <feOffset dx="2" dy="2"/>
11 </filter>

 第1行
  源程序开始并给这一滤镜命名
 第2行
  进行高斯模糊。stdDeviation的值赿大,图像就赿模糊。
 第3-9行
  滤镜使用一个数值矩阵表示如何改变图像的颜色。6、7、8、9表明如何改变图像的红、绿、蓝、α(透明度)通道,这4行中的每一行给出了红、绿、蓝、α的比例和一个校正值。以第6行为例,它表明当前像素点的红色的比例为100%,其中不包括绿、蓝二色,也没有透明度,不使用校正值把这些因素混合在一块儿(也就是最后的那一个0),所有这些将成为这个象互点的红色部分的新的值。简单地说,第6行使像素的红色仍然保持其原来的色度,而不在其中掺杂其他任何颜色,同样,第7行代码保持原来的绿色不变,第8行则完全剔除了原来的蓝色,第9行代码保持原来的透明度不变。这一滤镜的最终结果将图像由灰色改为黄色的。
 第10行
  这一滤镜对图像进行由dx、dy指定的距离的偏移 ,在这里,我们使用它就可以避免以后再执行transform=translate()了。

   现在我们把文本对象、第一个滤镜、第二个滤镜组合起来,其中第一个滤镜必须在第二个滤镜的前面,这样它显示的效果未能显示在第二个滤镜的下面。

<g transform="rotate(-90) translate(-100,180) scale(1.5,1)">
<use xlink:href="#megaText" fill="whitw"
filter="url(#glowShadowFilter)"/>
<use xlink:href="#megaText"/></g>


posted on 2006-04-05 17:50  王者归来  阅读(2175)  评论(0)    收藏  举报

导航