02 SVG 基础入门,原生绘制一个流程图

597 阅读8分钟

引言

在上一篇中我们提到了,流程图库的实现技术方案中主要有 SVG 和 Canvas,为了方便后续的学习,这一章我们将带大家学习一下 SVG 相关的知识,并着重介绍下在流程图库中可能用到的一些技术点,并用原生的 SVG 绘制一个原始概念上的流程图。本章不会涉及太多的拓展知识,如果大家对 SVG 感兴趣,可以通过大漠老师的 《深入浅出 SVG》课程深入学习。

什么是 SVG

可缩放矢量图形(Scalable Vector Graphics, SVG)基于 XML 标记语言,用于描述二维的矢量图形。

首先,援引 MDN 文档中对于 SVG 的解释,看不太懂吧 o.0。那我们用通俗的语言解释一下,SVG 是一种用来绘制图形的格式,简单来说,它就是一种基于代码的图片。可以把它理解为用文字描述图形的方式。

比如,我们通常见的图片(如 JPEG 或 PNG)是由像素点组成的,所以当你放大这些图片时,图像会模糊,因为它是用无数的小点拼起来的。而 SVG 不同,它是用数学公式来描述图形的,比如说”这里画一个圆、那边画一个方块“,所以无论怎样放大缩小,它都不会失真,图像始终保持清晰。

SVG 文件就像网页里的代码一样,可以直接嵌入到网页中,并且你可以用代码去修改它,比如改变颜色、形状,甚至加上交互功能(点击、拖动等)。所以它特别适合那些需要放大缩小、精确显示的图形,比如流程图图标或者一些网页上的小动画。

SVG 的语法介绍

基本结构

SVG 文件或元素的基本结构如下:

<!-- 示例代码 -->
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <!-- 图形元素 -->
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
  • xmlns="http://www.w3.org/2000/svg": 这是SVG 的命名空间,告诉浏览器这是一个 SVG 文件
  • widthheight:制定了 SVG 画布的宽度和高度
  • <svg> 标签中,我们可以插入各种图形元素,如矩形、圆形、线条等(上面我们插入了一个圆形)

概念介绍

常见元素

  • <rect>:绘制矩形
  • <circle>:绘制圆形
  • <line>:绘制直线
  • <text>:绘制文本
  • <path>:路径,绘制复杂图形

常见属性

  • fill:填充颜色
  • stroke:边框颜色
  • stroke-width:边框宽度

嵌入方式

如何在 HTML 中嵌入 SVG,可以直接嵌入 SVG 代码,即直接将 svg 元素写在 HTML中;也可以通过 <img> 标签使用,如下所示:

<img src="image.svg" alt="Description of the image" width="300" height="200" />
  • src="image.svg":指定 SVG 文件的路径,可以是本地文件路径或外部 URL。
  • alt="...":为 SVG 图像提供替代文本,提升无障碍性,特别是在图像无法加载时显示该文本。
  • widthheight:指定图像的宽度和高度,SVG 图像可以无损缩放,因此指定任意大小图像仍然保持清晰。

使用 SVG 绘制一个流程图

了解上面的基础概念后,我们直接上手撸一个简单的流程图,主要包括以下这些元素:

  1. 开始节点(圆形)
  2. 处理步骤(矩形)
  3. 判断条件(菱形)
  4. 连接这些形状的线条

1. 创建一个流程图画布

首先,定义一个 400x300 大小的 SVG 画布:

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">
  <!-- 图形内容将在这里绘制 -->
</svg>

2. 添加开始节点(圆形)

使用 <circle> 标签来绘制一个圆形,表示流程的开始节点。cx 和 cy 定义圆心的坐标,r 定义半径,fill 定义填充颜色。

<circle cx="50" cy="50" r="30" fill="lightblue" stroke="black" stroke-width="2"/>
<text x="50" y="55" font-size="16" text-anchor="middle" fill="black">开始</text>

说明:

  • 圆心坐标为 (50, 50),半径为 30
  • fill="lightblue" 表示圆的填充颜色为浅蓝色,stroke=“black" 表示边框色为黑色
  • 使用 <text> 元素在圆的中间添加 "开始" 文字

3. 添加处理步骤(矩形)

使用 <rect> 标签绘制矩形表示处理步骤,并添加对应的文字说明。

<rect x="130" y="35" width="100" height="30" fill="lightgreen" stroke="black" stroke-width="2"/>
<text x="180" y="55" font-size="16" text-anchor="middle" fill="black">处理</text>

说明:

  • 矩形的左上角坐标为 (150, 35),宽度为 100,高度为 30
  • 矩形内的文本内容为“处理”

4. 添加判断条件

菱形可以通过旋转矩形来实现,用 <polygon> 标签绘制。

<polygon points="300,30 330,50 300,70 270,50" fill="lightyellow" stroke="black" stroke-width="2"/>
<text x="300" y="55" font-size="16" text-anchor="middle" fill="black">判断</text>

说明:

  • points 定义了菱形的四个顶点坐标
  • 菱形内添加了“判断”文字

5. 添加连线

使用 <line> 标签绘制连接不同流程步骤的线条。

<line x1="80" y1="50" x2="130" y2="50" stroke="black" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="230" y1="50" x2="270" y2="50" stroke="black" stroke-width="2" marker-end="url(#arrow)"/>

说明:

  • x1, y1x2, y2 分别是线段的起点和终点坐标
  • stroke="black" 表示线条颜色为黑色

为了在连线的末端加上箭头,我们需要定义一个箭头标记:

<defs>
  <marker id="arrow" markerWidth="10" markerHeight="10" refX="5" refY="3" orient="auto" markerUnits="strokeWidth">
    <path d="M0,0 L0,6 L9,3 z" fill="black"/>
  </marker>
</defs>

这个箭头会在流程图的连线上自动显示

6. 完整代码

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">
  <defs>
    <marker id="arrow" markerWidth="10" markerHeight="10" refX="5" refY="3" orient="auto" markerUnits="strokeWidth">
      <path d="M0,0 L0,6 L5,3 z" fill="black"/>
    </marker>
  </defs>

  <!-- 开始节点 -->
  <circle cx="50" cy="50" r="30" fill="lightblue" stroke="black" stroke-width="2"/>
  <text x="50" y="55" font-size="16" text-anchor="middle" fill="black">开始</text>

  <!-- 处理步骤 -->
  <rect x="130" y="35" width="100" height="30" fill="lightgreen" stroke="black" stroke-width="2"/>
  <text x="180" y="55" font-size="16" text-anchor="middle" fill="black">处理</text>

  <!-- 判断条件 -->
  <polygon points="300,30 330,50 300,70 270,50" fill="lightyellow" stroke="black" stroke-width="2"/>
  <text x="300" y="55" font-size="16" text-anchor="middle" fill="black">判断</text>

  <!-- 连线 -->
  <line x1="80" y1="50" x2="130" y2="50" stroke="black" stroke-width="2" marker-end="url(#arrow)"/>
  <line x1="230" y1="50" x2="270" y2="50" stroke="black" stroke-width="2" marker-end="url(#arrow)"/>
</svg>

效果图如下:

image.png

其它一些常用知识点

使用路径绘制复杂图形

SVG 的 <path> 元素是用于绘制复杂形状的强大工具。通过一个 d 属性定义路径数据,可以精确地描述线条、曲线和其它复杂几何形状。它是 SVG 中最灵活、最强大的绘图元素

1. 基本结构

一个<path>元素的基本语法如下:

<path d="M10 10 H 90 V90 H 10 Z" fill="none" stroke="black" />

说明:

  • d 属性: 包含路径数据的字符串,定义路径的形状
  • stroke 属性:设置路径的描边颜色
  • fill 属性:设置路径内部的填充颜色

2. d 属性指令介绍

d 属性由一系列命令和参数组成。以下是一些常见的命令:

(1) 直线相关

  • M x y (Move To)
    移动到自定坐标点 (x, y),不绘制线条

    • 绝对坐标:M(大写)
    • 相对坐标:m(小写)
  • L x y (Line To)
    从当前点绘制一条直线到 (x, y)

    • 绝对:L
    • 相对:l
  • H x / V y

    • H:水平直线到指定的 x 坐标。
    • V:垂直直线到指定的 y 坐标

(2) 曲线相关

  • C x1 y1, x2 y2, x y (Cubic Bezier Curve)
    绘制三次贝塞尔曲线,控制点为 (x1, y1) 和 (x2, y2),终点为 (x, y)。

  • S x2 y2, x y (Smooth Cubic Bezier Curve)
    平滑三次贝塞尔曲线,第一个控制点自动计算,第二个控制点为 (x2, y2),终点为 (x, y)。

  • Q x1 y1, x y (Quadratic Bezier Curve)
    绘制二次贝塞尔曲线,控制点为 (x1, y1),终点为 (x, y)。

  • T x y (Smooth Quadratic Bezier Curve)
    平滑二次贝塞尔曲线,控制点自动计算,终点为 (x, y)。

(3) 圆弧相关

  • A rx ry x-axis-rotation large-arc-flag sweep-flag x y (Arc To)
    绘制圆弧:
    • rx / ry:椭圆的 x 和 y 半径
    • x-axis-rotation:x 轴旋转角度
    • large-arc-flag:大弧标志(1 为大弧,0 为小弧)
    • sweep-flag:弧线方向(1 为顺时针,0 为逆时针)
    • (x, y):终点坐标

(4) 关闭路径

  • Z z (Close Path)
    关闭当前路径,连接起点和终点。

3. 示例

示例 1:矩形

<path d="M10 10 H 90 V90 H 10 Z" fill="none" stroke="black" />

说明:

  • M10 10:移动到 (10, 10)。
  • H90:水平线到 x=90。
  • V90:垂直线到 y=90。
  • H10:水平线回到 x=10。
  • Z:闭合路径。 

示例 2:圆弧

<path d="M50 50 A40 40 0 1 1 90 90" fill="none" stroke="black" />

说明:

  • M50 50:移动到 (50, 50)。
  • A40 40 0 1 1 90 90:绘制一个半径为 40 的椭圆弧,起点 (50, 50),终点 (90, 90),顺时针方向,使用大弧。

4. 优点

  • 灵活性高:可以绘制任何形状
  • 高效:减少了节点数量和文件体积
  • 组合型强:可以结合直线和曲线,创建复杂的几何图形

5. 注意事项

  1. 命令大小写:大写为绝对坐标,小写为相对坐标
  2. 路径优化:路径数据可以简化,减少文件大小
  3. 填充规则:通过 fill-rule 控制路径的填充方式,如 nonzero 和 evenodd

动画和交互性

SVG 动画

如何使用 <animation> 元素创建简单动画

CSS 与 JavaScript 交互

  1. 如何通过 CSS 为 SVG 元素添加样式
  2. 使用 JavaScript 控制 SVG 的动态效果

动画示例

让一个圆形在页面加载后移动

<circle cs="50" cy="50" r="40" fill="blue">
  <animation attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite" />
</circle>

高级 SVG 技巧

  1. 渐变与图案填充:使用 <linearGradient><pattern> 创建渐变和图案效果
  2. 滤镜效果:使用 <filter> 为图形添加阴影、模糊等效果
  3. 文本与 SVG 的结合:如何使用 <text> 元素在 SVG 中嵌入文本,并设置字体样式

总结

通过这篇文章,我们学习了 SVG 的基础知识,并使用原生 SVG 绘制了一个简单的流程图。SVG 的优势在于它是矢量图形,能够在放大时保持清晰,同时提供丰富的交互性。通过掌握 SVG 的基础语法和常用元素,你可以创建更加复杂和灵活的图形,用于展示流程图、图标或其他可视化内容。

下一步,你可以尝试添加更多的图像元素,并通过 CSS 和 JavaScript 与 SVG 进行交互,创建更高级的流程图应用。而在下一篇中,我们将介绍另一种技术方案-Canvas的基础知识