Markdown 进阶语法:Mermaid 绘图 (二) - 顺序图 (Sequence Diagram)

Mermaid 简介

Mermaid 是一个基于 JavaScript 的图表绘制工具,它使用类似 Markdown 的简单语法来编写,并动态地将它们渲染成图表。

Mermaid 支持的图表类型包括:

  1. 流程图 (Flowchart) : 用关键词 graphflowchart 表示
  2. 顺序图 (Sequence Diagram) : 用关键词 sequenceDiagram 表示
  3. 类图 (Class Diagram) : 用关键词 classDiagram 表示
  4. 状态图 (State Diagram) : 用关键词 stateDiagram 表示
  5. 实体关系图 (Entity Relationship Diagram) : 用关键词 erDiagram 表示
  6. 用户旅程图 (User Journey Diagram) : 用关键词 journey 表示
  7. 甘特图 (Gantt Diagram) : 用关键词 gantt 表示
  8. 饼图 (Pie Chart Diagram) : 用关键词 pie 表示
  9. 象限图 (Quadrant Chart) : 用关键词 quadrantChart 表示
  10. 需求图 (Requirement Diagram) : 用关键词 requirementDiagram 表示
  11. Gitgraph 图 (Gitgraph Diagram) : 用关键词 gitGraph 表示
  12. 思维导图 (Mindmap) : 用关键词 mindmap 表示
  13. 时间线图 (Timeline Diagram) : 用关键词 timeline 表示

丰富的图表类型,可以满足大部分的绘图需求,越来越多的人开始使用 Mermaid 来绘制图表。


如何使用 Mermaid

想要使用 Mermaid 绘制各类图表,可以通过以下方式:

  • 使用专门支持 Mermaid 渲染的在线编辑器,如:Mermaid Live Editor
  • 使用支持 Mermaid 语法的 Markdown 编辑器,如:Typora

通常在专门的 Mermaid 编辑器我们只需要编写 Mermaid 语法,就可以看到图表的渲染效果:

1
2
3
4
5
6
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]

但是在支持 Mermaid 的 Markdown 编辑器中,我们需要在 Mermaid 语法前后添加特定的标记,才能看到图表的渲染效果,如:

1
2
3
4
5
6
7
8
```mermaid
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
```

Mermaid 语法

顺序图 (Sequence Diagram)

顺序图是一种交互图,它显示了流程如何相互操作以及以何种顺序操作。

Mermaid 可以渲染顺序图。

代码:

1
2
3
4
sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!

顺序图

由于 Mermaid 的语法规定,单词 end 可能会影响图表的语法结构。如果不可避免的要使用 end,请使用 括号 ()[]{} 或引号 "" 将其包裹起来。


Participants

参与者可以隐式地定义,如本文第一个示例所示。参与者在图源文本中按顺序呈现。有时,你可能希望以不同于上述示例中的顺序显示参与者,可以通过执行以下操作来指定它们的顺序:

1
2
3
4
5
sequenceDiagram
participant Alice
participant Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

Participants

Actors

如果你想使用 actor 图标来代替矩形框,可以使用 actor 关键字来代替 participant 关键字。

1
2
3
4
5
sequenceDiagram
actor Alice
actor Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

Actors

别名

每个参与者可以有一个标识符和一个别名。

1
2
3
4
5
sequenceDiagram
participant A as Alice
participant J as John
A->>J: Hello John, how are you?
J->>A: Great!

别名

分组

参与者可以分组。你可以通过以下方式定义一个颜色(默认为透明):

1
2
3
4
5
6
7
8
9
box Aqua Group Description
... actors ...
end
box Group without description
... actors ...
end
box rgb(33,66,99)
... actors ...
end

如果你的组名为颜色标识符,你也可以使用 transparent 关键字来定义一个透明的组:

1
2
3
box transparent Aqua
... actors ...
end

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
sequenceDiagram
box Purple Alice & John
participant A
participant J
end
box Another Group
participant B
participant C
end
A->>J: Hello John, how are you?
J->>A: Great!
A->>B: Hello Bob, how is Charly ?
B->>C: Hello Charly, how are you?

分组

消息

消息可以显示为实线或虚线两种形式。

1
[Actor][Arrow][Actor]:Message text

Mermaid 支持以下箭头:

类型描述
->无箭头实线
-->无箭头虚线
->>带箭头实线
-->>带箭头虚线
-xx 的实线
--xx 的虚线
-)) 的实线 (async)
--)) 的虚线 (async)

激活

你可以使用 activatedeactivate 关键字来激活或停用参与者。

1
2
3
4
5
sequenceDiagram
Alice->>John: Hello John, how are you?
activate John
John-->>Alice: Great!
deactivate John

激活1

还有一种直接在消息后面添加 +- 来激活或停用参与者的方法。

1
2
3
sequenceDiagram
Alice->>+John: Hello John, how are you?
John-->>-Alice: Great!

激活2

激活是可以堆叠的,如下所示:

1
2
3
4
5
sequenceDiagram
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
John-->>-Alice: I feel great!

激活3

说明

可以使用 Note 关键字添加说明。

1
Note [ right of | left of | over ] [Actor]: Text in note content

代码:

1
2
3
sequenceDiagram
participant John
Note right of John: Text in note

说明1

也可以添加跨越多个参与者的说明:

1
2
3
sequenceDiagram
Alice->John: Hello John, how are you?
Note over Alice,John: A typical interaction

说明2

也可以添加换行符:

1
2
3
sequenceDiagram
Alice->John: Hello John, how are you?
Note over Alice,John: A typical interaction<br/>But now in two lines

说明3

循环

可以在顺序图中使用 loop 关键字来定义循环。

1
2
3
loop Loop text
... statements ...
end

代码:

1
2
3
4
5
sequenceDiagram
Alice->John: Hello John, how are you?
loop Every minute
John-->Alice: Great!
end

循环

选择

可以在顺序图中使用 alt 关键字来定义选择。

1
2
3
4
5
alt Describing text
... statements ...
else
... statements ...
end

或者存在可选的序列:

1
2
3
opt Describing text
... statements ...
end

代码:

1
2
3
4
5
6
7
8
9
10
sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
alt is sick
Bob->>Alice: Not so good :(
else is well
Bob->>Alice: Feeling fresh like a daisy
end
opt Extra response
Bob->>Alice: Thanks for asking
end

选择

并行

可以在顺序图中使用 par 关键字来定义并行。

1
2
3
4
5
6
7
par [Action 1]
... statements ...
and [Action 2]
... statements ...
and [Action N]
... statements ...
end

代码:

1
2
3
4
5
6
7
8
sequenceDiagram
par Alice to Bob
Alice->>Bob: Hello guys!
and Alice to John
Alice->>John: Hello guys!
end
Bob-->>Alice: Hi Alice!
John-->>Alice: Hi Alice!

并行1

并行块也可以嵌套:

1
2
3
4
5
6
7
8
9
10
11
sequenceDiagram
par Alice to Bob
Alice->>Bob: Go help John
and Alice to John
Alice->>John: I want this done today
par John to Charlie
John->>Charlie: Can we do this today?
and John to Diana
John->>Diana: Can you help us today?
end
end

并行2

临界区

可以通过条件处理显示必须自动发生的操作。

1
2
3
4
5
6
7
critical [Action that must be performed]
... statements ...
option [Circumstance A]
... statements ...
option [Circumstance B]
... statements ...
end

代码:

1
2
3
4
5
6
7
8
sequenceDiagram
critical Establish a connection to the DB
Service-->DB: connect
option Network timeout
Service-->Service: Log error
option Credentials rejected
Service-->Service: Log different error
end

临界区1

只有一个选择时,也可以使用临界区:

1
2
3
4
sequenceDiagram
critical Establish a connection to the DB
Service-->DB: connect
end

临界区2

临界区也可以嵌套,详情参考 par

Break

可以在流中指示序列的停止(通常用于对异常建模)。

1
2
3
break [something happened]
... statements ...
end

代码:

1
2
3
4
5
6
7
sequenceDiagram
Consumer-->API: Book something
API-->BookingService: Start booking process
break when the booking process fails
API-->Consumer: show failure
end
API-->BillingService: Start billing process

Break

背景高亮

可以改变背景颜色来突出显示一些内容。

1
2
3
4
5
6
rect rgb(0, 255, 0)
... content ...
end
rect rgba(0, 0, 255, .1)
... content ...
end

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sequenceDiagram
participant Alice
participant John

rect rgb(191, 223, 255)
note right of Alice: Alice calls John.
Alice->>+John: Hello John, how are you?
rect rgb(200, 150, 255)
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
end
John-->>-Alice: I feel great!
end
Alice ->>+ John: Did you want to go to the game tonight?
John -->>- Alice: Yeah! See you there.

背景高亮

注释

可以在序列图中输入注释,解析器将忽略这些注释。使用 %% 标志注释的开始。

1
2
3
4
sequenceDiagram
Alice->>John: Hello John, how are you?
%% this is a comment
John-->>Alice: Great!

注释

转义字符的实体代码

可以使用 HTML 实体代码来转义字符。

1
2
3
sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!

转义字符的实体代码

顺序标号

在顺序图中,可以为每个箭头附加一个顺序标号。它可以在配置项中配置:

1
2
3
<script>
mermaid.initialize({ sequence: { showSequenceNumbers: true } });
</script>

也可以在图表语法中使用 autonumber 关键字打开:

1
2
3
4
5
6
7
8
9
10
sequenceDiagram
autonumber
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!

顺序标号

参与者菜单

参与者可以有包含到外部页面的个性化链接的弹出式菜单。例如,如果参与者表示 web 服务,则有用的链接可能包括指向服务运行状况指示板的链接、包含服务代码的 repo 或描述服务的 wiki 页面。

语法格式如:

1
link <actor>: <link-label> @ <link-url>

代码:

1
2
3
4
5
6
7
8
9
10
sequenceDiagram
participant Alice
participant John
link Alice: Dashboard @ https://dashboard.contoso.com/alice
link Alice: Wiki @ https://wiki.contoso.com/alice
link John: Dashboard @ https://dashboard.contoso.com/john
link John: Wiki @ https://wiki.contoso.com/john
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!

参与者菜单1

你也可以使用 json 来定义参与者菜单:

语法格式如:

1
links <actor>: <json-formatted link-name link-url pairs>

代码:

1
2
3
4
5
6
7
8
sequenceDiagram
participant Alice
participant John
links Alice: {"Dashboard": "https://dashboard.contoso.com/alice", "Wiki": "https://wiki.contoso.com/alice"}
links John: {"Dashboard": "https://dashboard.contoso.com/john", "Wiki": "https://wiki.contoso.com/john"}
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!

参与者菜单1

样式

顺序图的样式设置是通过定义一些 css 类来完成的。在渲染过程中,这些类从位于 src/themes/sequence.scss 的文件中提取出来。

用到的类

描述
actor图顶部的参与者框的样式
text.actor图表顶部参与者框中文本的样式
actor-line参与者之间的水平线的样式
messageLine0实线消息线的样式
messageLine1虚线消息线的样式
messageText消息线上文本的样式
labelBox循环中标签的样式
labelText循环中标签文本的样式
loopText循环框中文本的样式
loopLine循环框中线的样式
note说明框的样式
noteText说明中文本的样式

样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
body {
background: white;
}

.actor {
stroke: #ccccff;
fill: #ececff;
}
text.actor {
fill: black;
stroke: none;
font-family: Helvetica;
}

.actor-line {
stroke: grey;
}

.messageLine0 {
stroke-width: 1.5;
stroke-dasharray: '2 2';
marker-end: 'url(#arrowhead)';
stroke: black;
}

.messageLine1 {
stroke-width: 1.5;
stroke-dasharray: '2 2';
stroke: black;
}

#arrowhead {
fill: black;
}

.messageText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
}

.labelBox {
stroke: #ccccff;
fill: #ececff;
}

.labelText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
}

.loopText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
}

.loopLine {
stroke-width: 2;
stroke-dasharray: '2 2';
marker-end: 'url(#arrowhead)';
stroke: #ccccff;
}

.note {
stroke: #decc93;
fill: #fff5ad;
}

.noteText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
}

配置

可以使用 json 格式的配置对象 mermaid.sequenceConfigmermaid.sequenceConfig 来配置顺序图。

1
2
3
4
5
6
7
8
mermaid.sequenceConfig = {
diagramMarginX: 50,
diagramMarginY: 10,
boxTextMargin: 5,
noteMargin: 10,
messageMargin: 35,
mirrorActors: true,
};

可能的配置参数

参数描述默认值
mirrorActors打开/关闭参与者在图表下方和上方的渲染false
bottomMarginAdj调整图形结束的位置。css 的宽边框样式可能会产生不必要的剪切,这就是这个配置参数存在的原因。1
actorFontSize设置参与者描述的字体大小14
actorFontFamily设置参与者描述的字体类“Open Sans”, sans-serif
actorFontWeight设置参与者描述的字体粗细“Open Sans”, sans-serif
noteFontSize设置参与者附加说明的字体大小14
noteFontFamily设置参与者附加注释的字体类“trebuchet ms”, verdana, arial
noteFontWeight设置参与者附加说明的字体粗细“trebuchet ms”, verdana, arial
noteAlign设置参与者附加说明中的文本对齐方式center
messageFontSize设置参与者之间消息的字体大小16
messageFontFamily设置参与者之间消息的字体类“trebuchet ms”, verdana, arial
messageFontWeight设置参与者之间消息的字体粗细“trebuchet ms”, verdana, arial