[学习笔记] - SVG图片

SVG是XML语言的一种形式,有点类似XHTML,它可以用来绘制矢量图形。SVG可以通过定义必要的线和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来创建图形。图形和其组成部分可以变形,可以合成,还可以通过滤镜完全改变外观。

绘制流程包括以下几步:

  • 应舍弃来自 (X)HTML的doctype声明,因为基于SVG的DTD验证导致的问题比它能解决的问题更多。
  • 属性version和属性baseProfile属性是必不可少的,供其它类型的验证方式确定SVG版本。
  • 作为XML的一种方言,SVG必须正确的绑定命名空间 (在xmlns属性中绑定)。

网格

对于所有元素,SVG使用的坐标系统或者说网格系统,和Canvas用的差不多(所有计算机绘图都差不多)。这种坐标系统是:以页面的左上角为(0,0)坐标点,坐标以像素为单位,x轴正方向是向右,y轴正方向是向下。注意,这和你小时候所教的绘图方式是相反的。但是在HTML文档中,元素都是用这种方式定位的。

SVG 图形

矩形 <rect>

1
2
<rect x="10" y="10" width="30" height="30"/>
<rect x="60" y="10" rx="10" ry="10" width="30" height="30"/>
参数 描述
x 矩形左上角的x位置
y 矩形左上角的y位置
width 矩形的宽度
height 矩形的高度
rx 圆角的x方位的半径
ry 圆角的y方位的半径

圆形 <circle>

1
<circle cx="25" cy="75" r="20"/>
参数 描述
r 圆的半径
cx 圆心的x位置
cy 圆心的y位置

椭圆 <ellipse>

1
<ellipse cx="75" cy="75" rx="20" ry="5"/>
参数 描述
rx 椭圆的x半径
ry 椭圆的y半径
cx 椭圆中心的x位置
cy 椭圆中心的y位置

线 <line>

1
<line x1="10" x2="50" y1="110" y2="150"/>
参数 描述
x1 起点的x位置
y1 起点的y位置
x2 终点的x位置
y2 终点的y位置

折线 <polyline>

1
<polyline points="60 110, 65 120, 70 115, 75 130, 80 125, 85 140, 90 135, 95 150, 100 145"/>

points:点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。

多边形 <polygon>

1
<polygon points="50 160, 55 180, 70 180, 60 190, 65 205, 50 195, 35 205, 40 190, 30 180, 45 180"/>

points:点集数列。每个数字用空白符、逗号、终止命令或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。路径绘制完后闭合图形,所以最终的直线将从位置(2,2)连接到位置(0,0)。

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>

<svg width="400" height="180">
<rect x="50" y="20" width="150" height="150"
style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
</svg>

<svg width="400" height="180">
<rect x="50" y="20" width="150" height="150"
style="fill:blue;stroke:pink;stroke-width:5;opacity:0.5" />
</svg>

<svg width="400" height="180">
<rect x="50" y="20" rx="20" ry="20" width="150" height="150"
style="fill:red;stroke:black;stroke-width:5;opacity:0.5" />
</svg>

Path

<path>元素用于定义一条路径。

直线命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 移动到
M x y
m dx dy

# 在当前位置和新位置之间画一条线段
L x y
l dx dy

# 绘制水平线
H x
h dx

# 绘制垂直线
V y
v dy

# 闭合路径
Z
z

曲线命令

贝塞尔曲线

1
C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)

最后一个坐标(x,y)表示的是曲线的终点
另外两个坐标是控制点

  • (x1,y1)是起点的控制点
  • (x2,y2)是终点的控制点
1
2
3
4
5
6
7
8
9
10
11
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
<path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/>
<path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="transparent"/>
<path d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent"/>
<path d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent"/>
<path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="transparent"/>
<path d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/>
<path d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="transparent"/>
<path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/>
</svg>

贝塞尔曲线命令S

1
S x2 y2, x y (or s dx2 dy2, dx dy)

S命令可以用来创建与前面一样的贝塞尔曲线,但是,如果S命令跟在一个C或S命令后面,则它的第一个控制点会被假设成前一个命令曲线的第二个控制点的中心对称点。如果S命令单独使用,前面没有C或S命令,那当前点将作为第一个控制点。

1
2
3
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
</svg>

二次贝塞尔曲线Q

1
Q x1 y1, x y (or q dx1 dy1, dx dy)

一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。

1
2
3
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"">
<path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
</svg>

<svg width=“190px” height=“160px” version=“1.1” xmlns=“http://www.w3.org/2000/svg”">

二次贝塞尔曲线T

1
T x y (or t dx dy)

快捷命令T会通过前一个控制点,推断出一个新的控制点。这意味着,在你的第一个控制点后面,可以只定义终点,就创建出一个相当复杂的曲线。需要注意的是,T命令前面必须是一个Q命令,或者是另一个T命令,才能达到这种效果。如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线。

弧形

1
2
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy

前两个参数分别是x轴半径和y轴半径

1
2
3
4
5
6
7
8
<svg width="320px" height="320px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 315
L 110 215
A 30 50 0 0 1 162.55 162.45
L 172.55 152.45
A 30 50 -45 0 1 215.1 109.9
L 315 10" stroke="black" fill="green" stroke-width="2" fill-opacity="0.5"/>
</svg>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg width="325px" height="325px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M80 80
A 45 45, 0, 0, 0, 125 125
L 125 80 Z" fill="green"/>
<path d="M230 80
A 45 45, 0, 1, 0, 275 125
L 275 80 Z" fill="red"/>
<path d="M80 230
A 45 45, 0, 0, 1, 125 275
L 125 230 Z" fill="purple"/>
<path d="M230 230
A 45 45, 0, 1, 1, 275 275
L 275 230 Z" fill="blue"/>
</svg>

属性

上色丨fill

fill属性设置对象内部的颜色

线条颜色丨stroke

stroke属性设置绘制对象的线条的颜色

描边丨stroke-linecap

  • butt

用直边结束线段,它是常规做法,线段边界90度垂直于描边的方向、贯穿它的终点。

  • square

会稍微超出实际路径的范围,超出的大小由stroke-width控制。

  • round

会稍微超出实际路径的范围,超出的大小由stroke-width控制。

线段连接点丨stroke-linejoin

  • miter

表示用方形画笔在连接处形成尖角

  • round

表示用圆角连接

  • bevel

连接处会形成一个斜接

上色属性

stroke-dasharray

参数:一组用逗号分割的数字组成的数列。

这里的数字必须用逗号分割(空格会被忽略)。每一组数字

  • 第一个用来表示填色区域的长度
  • 第二个用来表示非填色区域的长度。
1
2
3
4
5
6
<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M 10 75 Q 50 10 100 75 T 190 75" stroke="black"
stroke-linecap="round" stroke-dasharray="5,10,5" fill="none"/>
<path d="M 10 75 L 190 75" stroke="red"
stroke-linecap="round" stroke-width="1" stroke-dasharray="5,5" fill="none"/>
</svg>

fill-rule

重叠区域上色

stroke-dashoffset

虚线开始的位置

stroke-miterlimit

什么情况下绘制或不绘制边框连接的miter效果

渐变

线性渐变

需要在SVG文件的defs元素内部,创建<linearGradient>节点
使用渐变时,我们需要在一个对象的属性fill或属性stroke中引用它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<svg width="230" height="130" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
<style type="text/css"><![CDATA[
#rect1 { fill: url(#Gradient1); }
.stop1 { stop-color: red; }
.stop2 { stop-color: black; stop-opacity: 0; }
.stop3 { stop-color: blue; }
]]></style>
</defs>

<rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/>
<rect x="120" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>

</svg>

属性x1、x2、y1和y2:定义了渐变路线走向。渐变色默认是水平方向的,但是通过修改这些属性,就可以旋转该方向。

标签 作用
offset 偏移
stop-color 颜色中值
stop-opacity 某个位置的半透明度

径向渐变

径向渐变与线性渐变相似,只是它是从一个点开始发散绘制渐变。创建径向渐变需要在文档的defs中添加一个<radialGradient>元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<svg width="230" height="130" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="RadialGradient1">
<stop offset="0%" stop-color="red"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
<radialGradient id="RadialGradient2" cx="0.25" cy="0.25" r="0.25">
<stop offset="0%" stop-color="red"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
</defs>

<rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient1)"/>
<rect x="120" y="10" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient2)"/>

</svg>

径向渐变也是通过两个点来定义其边缘位置

  • 第一个点定义了渐变结束所围绕的圆环,它需要一个中心点,由cx和cy属性及半径r来定义,通过设置这些点我们可以移动渐变范围并改变它的大小,
  • 第二个点被称为焦点,由fx和fy属性定义。第一个点描述了渐变边缘位置,焦点则描述了渐变的中心,如下例。







(fx,fy) (cx,cy)

因为如果焦点如之前描述的那样被移到圆圈的外面,渐变将不能正确呈现,所以该点会被假定在圆圈范围内。如果没有给出焦点,将认为该点与中心点的位置一致。

渐变过程

spreadMethod该属性控制了当渐变到达终点的行为.

行为 描述
pad 默认
reflect 让渐变一直持续下去,不过它的效果是与渐变本身是相反的,以100%偏移位置的颜色开始,逐渐偏移到0%位置的颜色,然后再回到100%偏移位置的颜色
repeat 渐变继续,但是它不会像reflect那样反向渐变,而是跳回到最初的颜色然后继续渐变。

Pad
Repeat
Reflect

渐变单元丨gradientUnits

gradientUnits:用来描述渐变的大小和方向的单元系统。

作用
objectBoundingBox 默认,定义了对象的渐变大小范围,指定从0到1的坐标值,渐变就会自动的缩放到对象相同大小
userSpaceOnUse 绝对单元,所以你必须知道对象的位置,并将渐变放在同样地位置上。

图案

<pattern>需要放在SVG文档的<defs>内部。

  • pattern定义了一个单元系统以及他们的大小。
  • 在pattern元素内部可以包含任何之前包含过的其它基本形状
  • 每个形状都可以任何样式样式化

patternUnits

objectBoundingBox,当一个值为1时,它被缩放到应用pattern对象的宽高值。因此,我们希望pattern垂直和水平的重复4次,所以宽高被设置位0.25,这一位置pattern的宽高仅为总外框大小的0.25。

patternContentUnits

描述了pattern元素基于基本形状使用的单元系统,这个属性默认值为userSpaceOnUse,与patternUnits属性相反,这意味着除非你至少指定其中一个属性值(patternContentUnits或patternUnits)

文字

1
<text x="10" y="10">Hello World!</text>
属性 作用
x, y 文本在视口中显示的位置 start、middle、end或inherit
fill 上色
stroke 描边

下列每个属性可以被设置为一个SVG属性或者成为一个CSS声明

  • font-family
  • font-style
  • font-weight
  • font-variant
  • font-stretch
  • font-size
  • font-size-adjust
  • kerning
  • letter-spacing
  • word-spacing
  • text-decoration

tspan

该元素用来标记大块文本的子部分,它必须是一个text元素或别的tspan元素的子元素。一个典型的用法是把句子中的一个词变成粗体红色。

1
2
3
<text>
<tspan font-weight="bold" fill="red">This is bold and red</tspan>
</text>
标签 作用
x 为容器设置一个新绝对x坐标。它覆盖了默认的当前的文本位置。这个属性可以包含一个数列,它们将一个一个地应用到tspan元素内的每一个字符上。
dx 从当前位置,用一个水平偏移开始绘制文本。这里,你可以提供一个值数列,可以应用到连续的字体,因此每次累积一个偏移。
y 为容器设置一个新绝对y坐标。它覆盖了默认的当前的文本位置。这个属性可以包含一个数列,它们将一个一个地应用到tspan元素内的每一个字符上。
dy 从当前位置,用一个垂直偏移开始绘制文本。这里,你可以提供一个值数列,可以应用到连续的字体,因此每次累积一个偏移。
rotate 把所有的字符旋转一个角度。如果是一个数列,则使每个字符旋转分别旋转到那个值,剩下的字符根据最后一个值旋转。
textLength 这是一个很模糊的属性,给出字符串的计算长度。它意味着如果它自己的度量文字和长度不满足这个提供的值,则允许渲染引擎精细调整字型的位置。

tref

tref元素允许引用已经定义的文本,高效地把它复制到当前位置。你可以使用xlink:href属性,把它指向一个元素,取得其文本内容。你可以独立于源样式化它、修改它的外观。

1
2
3
4
5
<text id="example">This is an example text.</text>

<text>
<tref xlink:href="#example" />
</text>

textPath

该元素利用它的xlink:href属性取得一个任意路径,把字符对齐到路径,于是字体会环绕路径、顺着路径走:

1
2
3
4
<path id="my_path" d="M 20,20 C 40,40 80,40 100,20" />
<text>
<textPath xlink:href="#my_path">This text follows a curve.</textPath>
</text>

基础变形

平移丨translate()

1
<rect x="0" y="0" width="10" height="10" transform="translate(30,40)" />

旋转丨rotate()

1
<rect x="20" y="20" width="20" height="20" transform="rotate(45)" />

斜切丨skewX() skewY()

利用一个矩形制作一个斜菱形。可用skewX()变形和skewY()变形。每个需要一角度以确定元素斜切到多远。

缩放丨scale()

它需要两个数字,作为比率计算如何缩放。0.5表示收缩到50%。如果第二个数字被忽略了,它默认等于第一个值。

剪切

clip-path

1
2
3
4
5
6
7
8
9
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="cut-off-bottom">
<rect x="0" y="0" width="200" height="100" />
</clipPath>
</defs>

<circle cx="100" cy="100" r="100" clip-path="url(#cut-off-bottom)" />
</svg>

遮罩

遮罩的效果最令人印象深刻的是表现为一个渐变。如果你想要让一个元素淡出,你可以利用遮罩效果实现这一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="Gradient">
<stop offset="0" stop-color="white" stop-opacity="0" />
<stop offset="1" stop-color="white" stop-opacity="1" />
</linearGradient>
<mask id="Mask">
<rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" />
</mask>
</defs>

<rect x="0" y="0" width="200" height="200" fill="green" />
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />
</svg>

透明度

属性 作用
opacity 透明度
fill-opacity 填充透明度
stroke-opacity 描边透明度