认识一下 SVG

最后更新:
阅读次数:

SVG,即可缩放矢量图形(Scalable Vector Graphics),它能够以 XML 格式的文本表示图形信息。

基本形状

  • 线段
<line x1="100"
y1="100"
x2="300"
y2="300"
stroke="green"
stroke-width="2"/>
  • 矩形
<!-- 普通矩形 -->
<rect x="100"
y="100"
width="200"
height="100"
fill="red" />
<!-- 圆角矩形 -->
<rect x="100"
y="100"
width="200"
height="100"
rx="50"
ry="50"
fill="red" />
<circle cx="100"
cy="100"
r="50"
fill="red" />
  • 椭圆
<ellipse cx="100"
cy="100"
rx="80"
ry="40"
fill="red" />
  • 多边形
<polygon points="15,10 55,44 100,22 100,44 55,55"
fill="red" />
  • 折线
<polyline points="11,11 333,44 222,9 66,90"
stroke="green"
fill="none" />

其它 SVG 元素

  • <g> 元素,常用来组合元素,并且通常会为其分配一个 id 作为唯一名称
<g id="group1"> <!-- add some thing --> </g>
  • <use> 元素,常用来复用一个通过 g 元素组合的对象
<use xlink:href="#group1" x="70" y="90" />
  • <defs> 元素的作用是:将那些需要复用的组合对象放到其中,但是不会显示,只是进行定义
<defs>
<g id="group1"></g>
<g id="group2"></g>
<g id="group3"></g>
</defs>

<use xlink:href="#group1" x="99" y="66" />
<use xlink:href="#group3" x="11" y="6" />
  • <image> 元素,用于引用外部的 svg 文件或栅格图形文件
<image xlink:href="./test.jpg"
x="100"
y="100"
height="100"
width="200" />
  • <text> 元素为 SVG 引入文本
<text x="0" y="15" fill="red">I love SVG</text>
<!-- 为引入的文本添加超链接 -->
<a xlink:href="https://www.w3schools.com/graphics/" target="_blank">
<text x="0" y="15" fill="red">I love SVG!</text>
</a>
<!-- 为文本使用文本路径 -->
<defs>
<path id="myPath"
d="M150 58 C6 40 123 321 130 118" />
</defs>

<text style="stroke:red">
<textPath xlink:href="#myPath">
asdsadasdasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</textPath>
</text>

坐标系统

  • svg 的 widthheight 属性用来声明当前 svg 文档视口的大小
<svg
width="500"
height="500"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="100" y="100" width="200" height="100" />
</svg>

一旦 svg 的视口大小被声明出来后,最初的坐标系统用户坐标系统 也会同时被建立。默认情况下,这两个坐标系统是完全一样的,都是基于视口大小建立起来的。但是 在声明了 viewBox 属性 后,用户坐标系统将基于视口进行一定程度的缩放,以达到 viewBox 属性指定的效果。

而且实际上,用户坐标系统才是真正的坐标系统,所有的图形点的坐标都是基于这个用户坐标系统,而不是基于最初的坐标系统。

  • viewBox 属性: 为视口指定用户坐标系统
    • 有四个值:最小 x 坐标、最小 y 坐标、宽度、高度。
<svg
width="500"
height="500"
viewBox="0 0 200 200"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="100" y="100" width="100" height="50" />
</svg>

上面 viewBox 的宽高比正好和视口的宽高比一样,那如果两者的比率不一样呢?如果比率不一样,viewBox 还是会基于视口进行一定程度的缩放,默认情况下它会使自己全部显示在视口中,并且在水平和垂直上都会居中,这是因为 preserveAspectRatio 的默认值就是 xMidYMid meet

  • preserveAspectRatio 属性: 用来指定被缩放的 viewBox 相对视口的对齐方式,以及是希望它适配边缘还是要裁剪。
preserveAspectRatio="xAlignmentYAlignment [meet | slice]" xAlignment = [xMin |
xMid | xMax] yAlignment = [yMin | yMid | yMax]

preserveAspectRatio 还有一个值是 none,设定了这个值后,viewBox 将不会被保持原来的比率进行缩放,结果是它被横向或纵向拉伸。

<svg
width="500"
height="500"
viewBox="0 0 400 200"
preserveAspectRatio="none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="100" y="100" width="100" height="50" />
</svg>

坐标系统变换

当你为一个 svg 元素应用 transform 属性时,这个元素就会拷贝一个当前的坐标系统用来完成自己相应的变换。

  • SVG 中的变换变换的是拷贝后的坐标系统
    • translate(x, y): 移动坐标系统
    • scale(x, y): 缩放坐标系统
    • rotate(angle, centerX, centerY): 旋转坐标系统
    • skewX(angle): 倾斜 x 坐标轴
    • skewY(angle): 倾斜 y 坐标轴
<g id="rect">
<rect x="100"
y="100"
width="200"
height="100" />
</g>

<use xlink:href="#rect"
x="0"
y="0"
transform="scale(0.5) translate(0,120)" />

路径

path 元素是一个更通用的用来表示图形的 svg 元素,我们前面提到的所有的基本形状都可以通过 path 元素进行表示,但是为了让 svg 结构化以及增强可读性,建议尽可能地使用这些简写形式。

  • 所有描述轮廓的信息都放在 path 元素的 d(data 的简写)属性中
    • d 属性的值由一系列路径命令组成
    • 命令都由一个字母进行表示,并且大写字母后面跟绝对坐标,而小写字母后面跟相对坐标
    • 使用逗号或空格来分隔 x 和 y 坐标
### 路径命令

M 移动到给定坐标
L 绘制一条道给定坐标的直线
H 绘制一条到给定 x 坐标的水平直线
V 绘制一条到给定 y 坐标的水平直线
A 绘制一条椭圆弧
Q 绘制一条二次贝赛尔曲线
T 绘制一条光滑的二次贝赛尔曲线
C 绘制一条三次贝赛尔曲线
S 绘制一条光滑的三次贝赛尔曲线
Z 闭合路径,绘制一条终点到起点的直线
  • 书写更简洁的路径表示法的两条规则
    • 可以在 Ll 命令后放多组坐标
    • 所有不必要的空白都可以消除(命令字母与数字之间的空白可消除,正数和负数之间的空白也可消除)
<!-- 原始路径 -->
<path d="M 100,100 L 200,200 L 100,300 Z" />

<!-- 简洁的路径 -->
<path d="M100,100L200,200 100,300Z" />
  • 一个简单的动画

See the Pen simple-svg-animation by percy (@percy507) on CodePen.

SVG 的 CSS 属性

line {
stroke: green; /* 笔画颜色 */
stroke-width: 3; /* 笔画宽度 */
stroke-opacity: 0.5; /* 笔画透明度 */

/* 笔画效果,虚线、点线,它的值由一个或多个数字组成 */
stroke-dasharray: 10, 20, 5, 15;

/*
指定线段的头尾形状,butt、round(圆的)、square(平的)
round 和 square 的起止位置都超过了真实位置,默认值 butt 则精确地与起止位置对齐
*/
stroke-linecap: round;

/*
指定线段在图形棱角处交叉时的效果
miter(尖的)、round(圆的)、bevel(平的)
*/
stroke-linejoin: round;
}

rect {
fill: green; /* 填充的颜色 */
fill-opacity: 0.5; /* 填充颜色的透明度 */
}

其它的 CSS 属性用到了会再补充 ~


我上面有关坐标系统和坐标系统的变换讲的不太详细,大家可以看看下面的一系列文章,超级详细,并且配有可视化的图片,理解起来更容易。

Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio > Understanding SVG Coordinate Systems and Transformations (Part 2) — The transform Attribute > Understanding SVG Coordinate Systems and Transformations (Part 3) — Establishing New Viewports