Markdown 使用技巧之利用 Mermaid 进行绘制流程图

4,160 阅读10分钟

刘诗诗-15.jpeg

前言

  Markdown 的原生语法不支持绘制图形,但通过 Mermaid 扩展,我们可以将一些格式化的文字渲染成我们需要的图形。Mermaid 是一个类似 Markdown 的开源脚步语言,它能够根据输入的语句自动生成合适的图像,方便于 Markdown 文档撰写者通过文本方式生成图形的扩展工具。相比 Visio 它要轻很多,几行文字便可生成一幅完整且美观的流程图。

  Mermaid 中包含多种可以使用的图表定义结构,考虑到实用性和学习成本,仅重点学习几种图形语法,分别是流程图(FlowChart)、时序图(Sequence Diagram)、类图(Class Diagram)、状态图(State Diagram)、用户行程图(User Journey)、甘特图(Gantt)、饼图(Pie Chart)等。推荐的学习方法是随用随学,Mermaid 语法并不难学,根据需要进行学习是比较实用的方法。

  本文将重点介绍如何通过 Mermaid 绘制图,考虑到 Markdown 工具之间的不兼容,有的内容直接从页面复制粘贴到本地不会正常显示,有时还需要自己动手。本节所有实例代码及演示效果均使用 Typora 工具完成。Mermaid 为 Markdown 扩展语法,需要在 Typora 设置中开启对图表的语法支持。其方式为:「设置」->「Markdown」->「Markdown 扩展语法」-> 勾选「图表」,如下图:

5ebc19e308b2539714000960.jpeg

Mermaid 官网:mermaid.js.org/

Mermaid 在线渲染编辑器mermaid.live/

注意:需要注意的是,由于 Mermaid 本身还在发展,并非所有特性都能被所有 Markdown 编辑器支持。因此,某些效果展示我使用图片进行

流程图可以用于展示某个过程中各个步骤的顺序和关系,例如软件开发过程中的各个阶段、某个业务流程中的各个环节等等。

一、基础语法

1.1 声明图像类型

  告诉 Mermaid 下列语法是什么图像,可以用 flowchartgraph 声明流程图类型。在 Markdown 中添加 Mermaid 图形,需要声明 Mermaid 类型的代码块,关键字graph表示一个流程图的开始,同时需要指定该图的方向。代码如下:

```mermaid
<!-- 此处的内容会被渲染成 mermaid 图形 -->
```
  • 至于 flowchart、graph 声明流程图类型的区别,参考 扩展 4.1

1.2 声明排列方向

  声明完流程图图像类型后,还需要告诉 Mermaid 流程图的排列方向。其中:L代表Left左边R代表Right右边T代表Top上面B代表Bottom下面,顺序为左边的字母到右边的字母:

顺序字母代表意义顺序字母代表意义
RL从右到左LR从左到右
TB自上而下BT自下而上
TD等同于 TB
  • 基本的竖向流程图:

    ```mermaid
    graph TD
        开始 --> 结束
    ```
    

    此部分代码将会渲染成如下效果:

    graph TD
        开始 --> 结束
    
  • 基本的横向流程图:

    ```mermaid
    graph LR
        开始 --> 结束
    ```
    

    此部分代码将会渲染成如下效果:

    graph LR
        开始 --> 结束
    
  • 展示一个复杂的方向流程图

    ```mermaid
        flowchart TB
          subgraph 从左到右
            direction LR
            声明图像类型1 --> 声明排列方向1 --> 声明图像内容1
          end
          subgraph 从右到左
            direction RL
            声明图像类型2 --> 声明排列方向2 --> 声明图像内容2
          end
          subgraph 上下分明
            direction LR
            subgraph 从上到下
              direction TB
              声明图像类型3 --> 声明排列方向3 --> 声明图像内容3
            end
            subgraph 从下到上
              direction BT
              声明图像类型4 --> 声明排列方向4 --> 声明图像内容4
            end
            从上到下 --> 从下到上
          end
          从左到右 --> 从右到左 --> 上下分明
      ```
    

    此部分代码将会渲染成如下效果:

    flowchart TB
      subgraph 从左到右
        direction LR
        声明图像类型1 --> 声明排列方向1 --> 声明图像内容1
      end
      subgraph 从右到左
        direction RL
        声明图像类型2 --> 声明排列方向2 --> 声明图像内容2
      end
      subgraph 上下分明
        direction LR
        subgraph 从上到下
          direction TB
          声明图像类型3 --> 声明排列方向3 --> 声明图像内容3
        end
        subgraph 从下到上
          direction BT
          声明图像类型4 --> 声明排列方向4 --> 声明图像内容4
        end
        从上到下 --> 从下到上
      end
      从左到右 --> 从右到左 --> 上下分明
    

1.3 声明节点

  几何图形节点是流程图中的核心元素,在 Mermaid 语法中,有两种声明节点的方式:

  • 直接声明:直接在 连接声明区域声明节点,此时节点名字作为节点内容,节点样式采用默认样式(即 [] 样式)
  • 完整声明:使用 节点名字[节点内容] 声明节点,其中的 [] 代表节点样式,可以改变它以改变节点样式
```mermaid
graph LR
    直接声明
    M[完整声明]
```

此部分代码将会渲染成如下效果:

graph LR
    直接声明
    M[完整声明]

1.4 声明节点形状

  形状可用于区分节点的不同属性,有利于丰富流程图的信息量,同时保持其简洁性。在 Mermaid 中可以使用一些基本符号定义节点的形状,例如:圆角形、跑道形、气缸形、非对称形状、菱形、六角形、平行四边形、梯形。节点形状常用语法以及使用见下表:

节点样式节点语法节点样式节点语法节点样式节点语法
默认(文本)圆角矩形(文本)胶囊([文本])
子程序[[文本]]圆柱[(文本)]圆形((文本))
六边形{{文本}}棱形{文本}正四边形[/文本/]
反四边形[\文本\]正梯形[/文本\]反梯形[\文本/]
非对称的矩形>文本]双圆(((文本)))

  在 Mermaid 语法中,不加任何修饰的文字内容会被渲染成几何图形节点。这里需要特意说明下,”双圆“这个形状的节点支持的不算太好,个人建议是实际情况而定是否使用。其渲染结果如下:

graph TB
A
A1[默认]
A2(圆角矩形)
A3([胶囊])
A4[[子程序]]
A5[(圆柱)]
A6((圆形))
A7{{六边形}}
graph TB
A8{棱形}
A9[/正四边形/]
A10[\反四边形\]
A11[/正梯形\]
A12[\反梯形/]
A13>非对称的矩形]

1.5 声明节点间的连接

1.5.1 基本连接线

  声明节点间的连接使得有关联的节点能被 Mermaid 识别并绘制连接线,在流程图中,不同节点之间需要通过连接线来描述其相关性。

  • 声明单个连接语法A --> B能够声明一条 A 到 B 链接
  • 声明多个连接语法A --> B --> C能够声明A 到 B、B 到 C 共两条链接
  • 多个节点聚合声明语法A & B --> C能够对多个节点进行操作声明 A 到 C、B 到 C 共两条链接
```mermaid
graph LR
    A --> B
    B --> C --> D
    D --> E & F --> A
```

此部分代码将会渲染成如下效果:

graph LR
    A --> B
    B --> C --> D
    D --> E & F --> A

1.5.2 调整链接的长度

  在某些情况下,可以大致定义链接的长度而改善 Mermaid 画出的图形。Mermaid 内可以定义链接跨越的级数以调整链接长度,想要跨越多少级数,只需要在正常的连接符号上加入对应数量的-.=等符号即可。

graph LR
    subgraph 没调整链接长度之前
      direction TB
      %% A --> B 的链接声明是正常的
      A --> B --> D
      D --> E
      E --> B
    end
    subgraph 调整了链接长度之后
      direction TB
      %% A ---> B 的链接声明多了一个 - 符号
      %% 代表着跨1个级别
      A1 ---> B1 --> D1
      D1 --> E1
      E1 --> B1
    end
```mermaid
graph LR
    subgraph 没调整链接长度之前
      direction TB
      %% A --> B 的链接声明是正常的
      A --> B --> D
      D --> E
      E --> B
    end
    subgraph 调整了链接长度之后
      direction TB
      %% A ---> B 的链接声明多了一个 - 符号
      %% 代表着跨1个级别
      A1 ---> B1 --> D1
      D1 --> E1
      E1 --> B1
    end
```

1.5.3 调整链接的样式

  不同种类的连接线可以表示不同类型的关系,例如,无方向的连接线可用来表示相关性、有方向的连接线可以表示数据流向或者节点间的依赖关系;用实线表示强关联、用虚线表示弱关联等待。常见连接线类型如下所示:

样式语法样式效果样式语法样式效果样式语法样式效果
A1-->B1箭头连接A2---B2开放连接A3--text---B3标签连接
A4--text-->B4箭头标签连接A5-.-B5虚线开放连接A6-.->B6虚线箭头连接
A7-.text.-B7标签虚线连接A8-.text.->B8标签虚线箭头连接A9===B9粗线开放连接
A10==>B10粗线箭头连接A11==text===B11标签粗线开放连接A12==text==>B12标签粗线箭头连接
  • 使用 graph 将会渲染成如下效果:
graph TD
  A1-->B1
  A2---B2
  A3--text---B3
  A4--text-->B4
  A5-.-B5
  A6-.->B6
  A7-.text.-B7
  A8-.text.->B8
  A9===B9
  A10==>B10
  A11==text===B11
  A12==text==>B12
  • 使用 flowchart 将会渲染成如下效果:
flowchart TD
  A1-->B1
  A2---B2
  A3--text---B3
  A4--text-->B4
  A5-.-B5
  A6-.->B6
  A7-.text.-B7
  A8-.text.->B8
  A9===B9
  A10==>B10
  A11==text===B11
  A12==text==>B12

二、流程图-进阶使用

2.1 自定义节点样式

  Mermaid 方流程图不仅支持多种节点形状、连接线种类,而且还支持节点自定义样式。由于节点有独一无二的节点名字,当要修改节点样式时,可以根据节点名字定位节点位置,定义节点样式语法如下:

style 节点名字 fill:#000, stroke:#000, stroke-width:0px, color:#000
属性说明
style定义形状的样式
fill设置形状的填充颜色,可以是具体的颜色值(如"#FF0000"表示红色)或预定义的颜色名称(如"red"表示红色)。
stroke设置形状的边框颜色
stroke-width设置边框宽度,可以是具体的像素值(如"2px"表示2像素宽度)。
stroke-dasharray设置虚线样式等

下面是一个示例,演示如何为形状设置样式和颜色:

```mermaid
graph LR
A --> B --> C --> D
style A fill:#F0F0F0,stroke:#333,stroke-width:2px;
style B fill:#FFF,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5;
style C fill:#FFA500,stroke:#333,stroke-width:2px;
style D fill:#FFF,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5; 
```

渲染效果如下:

graph LR
A --> B --> C --> D
style A fill:#F0F0F0,stroke:#333,stroke-width:2px;
style B fill:#FFF,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5;
style C fill:#FFA500,stroke:#333,stroke-width:2px;
style D fill:#FFF,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5; 

  除了上述示例中的样式属性,Mermaid 还支持许多其他的样式属性,例如 font-size、font-weight、font-family、text-align、text-decoration 等,可以根据需要进行设置。使用 style 关键字可以将形状的样式和颜色与具体的业务逻辑和需求相匹配,使图表更加清晰和易于理解。

2.2 自定义形状大小

  在 Mermaid 中,可以使用 style 关键字为形状设置大小。要设置形状的大小,可以使用 width 和 height 样式属性。width 样式属性用于设置形状的宽度,height 样式属性用于设置形状的高度。下面是一个示例,演示如何为形状设置大小:

```mermaid
graph LR;
  A[Square] --> B((Circle));
  C(Rectangle) --> D{Diamond};

  style A fill:#f9c, width:80px, height:60px;
  style B stroke:#333,stroke-width:4px, width:60px, height:60px;
  style C fill:#f96,stroke:#333,stroke-width:2px, width:100px, height:80px;
  style D fill:#fc9,stroke:#f63,stroke-width:4px,stroke-dasharray: 5 5, width:80px, height:80px;
```
graph LR;
  A[Square] --> B((Circle));
  C(Rectangle) --> D{Diamond};

  style A fill:#f9c, width:80px, height:60px;
  style B stroke:#333,stroke-width:4px, width:60px, height:60px;
  style C fill:#f96,stroke:#333,stroke-width:2px, width:100px, height:80px;
  style D fill:#fc9,stroke:#f63,stroke-width:4px,stroke-dasharray: 5 5, width:80px, height:80px;

  在上面的示例中,我们为四个形状 A、B、C 和 D 设置了不同的大小。例如,我们使用 width 和 height 样式属性对形状的大小进行设置,使它们具有不同的宽度和高度。需要注意的是,形状的大小可以随需求进行调整,但过大或过小的形状可能会影响图表的可读性和美观性。因此,在设置形状的大小时需要根据具体的业务需求和图表设计进行合理的调整。

2.3 自定义链接样式

  由于链接没有像节点一样的节点名字,所以如果要定义单个链接的样式,那么需要使用它的被声明顺序号(从0开始)。如我声明了三条链接,当我想要为第二条链接添加一个独特的样式时,应该这样做

linkStyle 1 stroke:#000, stroke-width:0px, color:#000

其中的1就是该链接的被声明顺序号,假如要对全部连接进行改变,去掉顺序号即可

2.4 视图分组

  对于相对庞大的流程图,可以通过对视图分组,以区分体系内的不同模块,以及不同模块间的关联关系。

```mermaid
graph LR
	A --> B --> C --> D
    subgraph Subgraph A
        B1 --> C1 --> D1
    end

    subgraph Subgraph B
        B2 --> C2 --> D2
    end
```

此部分代码将会渲染成如下效果:

graph LR
	A --> B --> C --> D
    subgraph Subgraph A
        B1 --> C1 --> D1
    end

    subgraph Subgraph B
        B2 --> C2 --> D2
    end

注意:在子图表中定义的形状只能在该子图表中使用,不能在其他子图表或图表中使用。

三、使用场景及实例

  流程图常用于项目的需求分析和设计阶段,也较常出现于程序使用手册中。

3.1 竖向流程图

```mermaid
graph TD
    A31-->B
    A-->C
    B-->D
    C-->D
```

此部分代码将会渲染成如下效果:

graph TD
    A31-->B;
    A-->C;
    B-->D;
    C-->D;

3.2 冒泡排序流程图

```mermaid
graph LR
	执行1[i = 1]
  执行2[j = 0]
  执行3[i ++]
  执行4["a = arr[j], b = arr[j + 1]"]
  执行5[交换 a, b]
  执行6[j ++]
	判断1["i < n"]
	判断2["j < n - i"]
  判断3["a > b"]
  开始 --> 执行1
  执行1 --> 判断1
  判断1 --Y--> 执行2
  执行2 --> 判断2
  判断2 --Y--> 执行4
  判断2 --N--> 执行3
  执行3 --> 判断1
  执行4 --> 判断3
  判断3 --N--> 判断2
  判断3 --Y--> 执行5
  执行5 --> 执行6
  执行6 --> 判断2
  判断1 --N--> 结束
```

此部分代码将会渲染成如下效果:

graph LR
	执行1[i = 1]
  执行2[j = 0]
  执行3[i ++]
  执行4["a = arr[j], b = arr[j + 1]"]
  执行5[交换 a, b]
  执行6[j ++]
	判断1["i < n"]
	判断2["j < n - i"]
  判断3["a > b"]
  开始 --> 执行1
  执行1 --> 判断1
  判断1 --Y--> 执行2
  执行2 --> 判断2
  判断2 --Y--> 执行4
  判断2 --N--> 执行3
  执行3 --> 判断1
  执行4 --> 判断3
  判断3 --N--> 判断2
  判断3 --Y--> 执行5
  执行5 --> 执行6
  执行6 --> 判断2
  判断1 --N--> 结束

3.3 横向流程图

```mermaid
graph LR
	start[开始] --> input[输入A,B,C]
	input --> conditionA{A是否大于B}
	conditionA -- YES --> conditionC{A是否大于C}
	conditionA -- NO --> conditionB{B是否大于C}
	conditionC -- YES --> printA[输出A]
	conditionC -- NO --> printC[输出C]
	conditionB -- YES --> printB[输出B]
	conditionB -- NO --> printC[输出C]
	printA --> stop[结束]
	printC --> stop
	printB --> stop
```

  此部分代码将会渲染成如下效果:

graph LR
	start[开始] --> input[输入A,B,C]
	input --> conditionA{A是否大于B}
	conditionA -- YES --> conditionC{A是否大于C}
	conditionA -- NO --> conditionB{B是否大于C}
	conditionC -- YES --> printA[输出A]
	conditionC -- NO --> printC[输出C]
	conditionB -- YES --> printB[输出B]
	conditionB -- NO --> printC[输出C]
	printA --> stop[结束]
	printC --> stop
	printB --> stop

四、扩展

4.1 flowchart VS graph

在绘制流程图的时候,将 graph 替换成 flowchart,可以呈现节点之间的曲线连接。比之前生硬的折线段美观很多。同时,flowchart还可以实现不同子图(subgraph)之间的连通,并且允许箭头逆向。相比之下,graph就只能在节点和节点之间按照既定方向相连。不过官网上显示flowchart仍然是测试版本,功能上可能会有一些欠缺。

  • flowchart 效果
flowchart TB
    c1-->a2
    subgraph one
    a1-->a2
    end
    subgraph two
    b1
    end
    subgraph three
    c1-->c2
    end
    one --> two
    three --> two
    two --> c2
```mermaid
flowchart TB
    c1-->a2
    subgraph one
    a1-->a2
    end
    subgraph two
    b1
    end
    subgraph three
    c1-->c2
    end
    one --> two
    three --> two
    two --> c2
  • graph 效果
graph TD
    c1-->a2
    subgraph one
    a1-->a2
    end
    subgraph two
    b1
    end
    subgraph three
    c1-->c2
    end
```mermaid
graph TB
    c1-->a2
    subgraph one
    a1-->a2
    end
    subgraph two
    b1
    end
    subgraph three
    c1-->c2
    end
 ```

4.2 字符转义

当你要输入特殊字符(与语法相冲突的字符)时,可以使用" "包裹住你的文本,这样就没有关系了。此外 Mermaid 还支持 HTML 的实体(以&表示的字符)。

五、结语

把今天最好的表现当作明天最新的起点…...~

  投身于天地这熔炉,一个人可以被毁灭,但绝不会被打败!一旦决定了心中所想,便绝无动摇。迈向光明之路,注定荆棘丛生,自己选择的路,即使再荒谬、再艰难,跪着也要走下去!放弃,曾令人想要逃离,但绝境重生方为宿命。若结果并非所愿,那就在尘埃落定前奋力一搏!

划重点.gif