1. Mermaid #

Mermaid 是一种基于文本的图表绘制工具,可以用简单的文本语法生成流程图、时序图、类图、甘特图等。它被广泛支持于 GitHub、GitLab、Notion、Obsidian、Typora、语雀等平台。

在 Markdown 中,使用 mermaid 代码块即可嵌入图表:

flowchart TD
    A[开始] --> B[结束]

2. 流程图(Flowchart) #

流程图是最常用的图表之一。使用 flowchart 或旧的 graph 关键字声明。

2.1 方向 #

写法 含义 全称
TB / TD 从上到下 Top Bottom / Top Down
BT 从下到上 Bottom Top
LR 从左到右 Left Right
RL 从右到左 Right Left
flowchart TB
    Top --> Bottom
flowchart TB Top --> Bottom
flowchart TD
    Top --> Down
flowchart TD Top --> Down
flowchart BT
    Bottom --> Top
flowchart BT Bottom --> Top
flowchart LR
    Left --> Right
flowchart LR Left --> Right
flowchart RL
    Right --> Left
flowchart RL Right --> Left

TB 和 TD 效果相同,都是从上到下。日常用 TD 即可。

2.2 节点形状 #

节点用 ID[显示文本] 定义,不同括号代表不同形状:

语法 形状
A[文本] 矩形
B(文本) 圆角矩形
C([文本]) 体育场形(两端圆)
D[[文本]] 子程序形
E[(文本)] 数据库/圆柱形
F((文本)) 圆形
G>文本] 不对称形
H{文本} 菱形(判断)
I{{文本}} 六边形
J[/文本/] 平行四边形
K[\文本\] 反向平行四边形
L[/文本\] 梯形
M[\文本/] 反向梯形
flowchart LR
    A[A矩形] --> B(B圆角矩形)
    B --> C([C体育场])
    C --> D[[D子程序]]
    D --> E[(E数据库)]
    E --> F((F圆形))
    F --> G>G不对称形]
    G --> H{H菱形}
    H --> I{{I六边形}}
    I --> J[/J平行四边形/]
    J --> K[\K反向平行四边形\]
    K --> L[/L梯形\]
    L --> M[\M反向梯形/]
flowchart LR A[A矩形] --> B(B圆角矩形) B --> C([C体育场]) C --> D[[D子程序]] D --> E[(E数据库)] E --> F((F圆形)) F --> G>G不对称形] G --> H{H菱形} H --> I{{I六边形}} I --> J[/J平行四边形/] J --> K[\K反向平行四边形\] K --> L[/L梯形\] L --> M[\M反向梯形/]

2.3 连线与箭头 #

flowchart LR
    A --> B
    B --- C
    C -.-> D
    D ==> E
    E --是--> F
    F -->|否| G
    G -.可能.-> H
    G <--返回--> K
flowchart LR A --> B B --- C C -.-> D D ==> E E --是--> F F -->|否| G G -.可能.-> H G <--返回--> K

2.4 多节点连接 #

可以用 & 同时连接多个节点。第一行读作「A 指向 B,同时 B 和 C 都指向 D」;第二行读作「E 和 F 都指向 G」。

flowchart LR
    A --> B & C --> D
    E & F --> G
flowchart LR A --> B & C --> D E & F --> G

2.5 子图 #

使用 subgraph 标题 ... end 把若干节点框成一组。子图之间照常连边。方向可以单独指定,例如 subgraph id [标题]。

flowchart TB
    subgraph 子图1
        A[开始] --> B[处理]
    end
    subgraph 子图2
        C[结束]
    end
    B --> C
flowchart TB subgraph 子图1 A[开始] --> B[处理] end subgraph 子图2 C[结束] end B --> C

2.6 样式与类 #

单个节点用 style 节点ID 属性 直接上色。多个节点共用同一套样式时,先用 classDef 定义类,再用 class 挂上去。

flowchart LR
    A[A红色节点] --> B[B蓝色节点]
    C[C也是蓝色]

    style A fill:#f9a,stroke:#333,stroke-width:4px
    classDef blue fill:#bbf,stroke:#00f,stroke-width:2px
    class B,C blue
flowchart LR A[A红色节点] --> B[B蓝色节点] C[C也是蓝色] style A fill:#f9a,stroke:#333,stroke-width:4px classDef blue fill:#bbf,stroke:#00f,stroke-width:2px class B,C blue

2.7 点击事件 #

click 节点ID "链接" "悬停提示" 给节点加上可点击链接。GitHub 等部分平台会出于安全考虑禁用点击,本地预览一般可用。

flowchart LR
    A[百度]
    click A "https://www.baidu.com" "点击访问百度"
flowchart LR A[百度] click A "https://www.baidu.com" "点击访问百度"

2.8 注释 #

流程图里以 %% 开头的行是注释,不会画出来。

flowchart LR
    %% 这是一条注释,不会出现在图上
    A --> B
flowchart LR %% 这是一条注释,不会出现在图上 A --> B

3. 时序图(Sequence Diagram) #

时序图用来画「谁在什么时候给谁发了什么消息」。使用 sequenceDiagram 声明。

sequenceDiagram
    participant A as 用户
    participant B as 系统

    A->>B: 登录请求
    B-->>A: 返回登录页面
    A->>B: 输入账号密码
    B->>B: 验证信息
    B-->>A: 登录成功
sequenceDiagram participant A as 用户 participant B as 系统 A->>B: 登录请求 B-->>A: 返回登录页面 A->>B: 输入账号密码 B->>B: 验证信息 B-->>A: 登录成功

3.1 参与者 #

参与者会按声明顺序从左到右排列。不声明也能用,第一次出现时自动创建。

写法 含义
participant 名称 as 显示名 矩形参与者
actor 名称 as 显示名 人形图标(角色)
sequenceDiagram
    actor U as 用户
    participant S as 系统
    U->>S: 发起请求
    S-->>U: 返回结果
sequenceDiagram actor U as 用户 participant S as 系统 U->>S: 发起请求 S-->>U: 返回结果

3.2 消息箭头 #

消息写在箭头后面,格式是 发送方箭头接收方: 文字。

语法 含义
A->>B: 消息 实线实心箭头(常见请求)
A-->>B: 消息 虚线实心箭头(常见返回)
A-->B: 消息 虚线无箭头
A-)B: 消息 异步实线(开放箭头)
A--)B: 消息 异步虚线
A-xB: 消息 实线带叉(失败 / 丢失)
A--xB: 消息 虚线带叉
sequenceDiagram
    A->>B: 常规请求
    B-->>A: 常规返回
    A-->B: 虚线无箭头
    A-)B: 异步实线(开放箭头)
    A--)B: 异步虚线
    A-xB: 失败/丢失
    A--xB: 虚线带叉
sequenceDiagram A->>B: 常规请求 B-->>A: 常规返回 A-->B: 虚线无箭头 A-)B: 异步实线(开放箭头) A--)B: 异步虚线 A-xB: 失败/丢失 A--xB: 虚线带叉

3.3 激活与停用 #

激活条表示「这个参与者正在处理」。两种写法等价:箭头上加 + / -,或单独写 activate / deactivate。

sequenceDiagram
    participant A
    participant B

    A->>+B: 激活 B
    B-->>-A: 停用 B
    activate A
    A->>B: 消息
    deactivate A
sequenceDiagram participant A participant B A->>+B: 激活 B B-->>-A: 停用 B activate A A->>B: 消息 deactivate A

3.4 注释 #

Note 用来在图上加说明,不参与消息传递。

写法 位置
Note right of A: 文字 A 的右侧
Note left of B: 文字 B 的左侧
Note over A,B: 文字 覆盖 A 到 B 这一段
sequenceDiagram
    participant A
    participant B

    Note right of A: 右侧注释
    Note left of B: 左侧注释
    Note over A,B: 覆盖 A 和 B 的注释
sequenceDiagram participant A participant B Note right of A: 右侧注释 Note left of B: 左侧注释 Note over A,B: 覆盖 A 和 B 的注释

3.5 循环与条件 #

这几块都要配对写 end。alt / else 是分支,opt 是可选项,loop 是循环,par / and 是并行。

关键字 含义
loop 条件 循环
alt 条件 / else 多选一
opt 条件 可选(只有一条分支)
par / and 并行
sequenceDiagram
    participant A
    participant B

    loop 每分钟
        A->>B: 心跳检测
    end

    alt 成功
        B-->>A: 成功响应
    else 失败
        B-->>A: 失败响应
    end

    opt 可选
        A->>B: 可选消息
    end

    par 并行任务1
        A->>B: 任务1
    and 并行任务2
        A->>B: 任务2
    end
sequenceDiagram participant A participant B loop 每分钟 A->>B: 心跳检测 end alt 成功 B-->>A: 成功响应 else 失败 B-->>A: 失败响应 end opt 可选 A->>B: 可选消息 end par 并行任务1 A->>B: 任务1 and 并行任务2 A->>B: 任务2 end

4. 类图(Class Diagram) #

类图用来画类、字段、方法和它们之间的关系。使用 classDiagram 声明。类体里字段在上、方法在下,可见性用前缀符号表示。

classDiagram
    class Animal {
        +String name
        +int age
        +makeSound() void
    }
    class Dog {
        +fetch() void
    }
    Animal <|-- Dog
classDiagram class Animal { +String name +int age +makeSound() void } class Dog { +fetch() void } Animal <|-- Dog

4.1 成员可见性 #

写在字段或方法前面:

前缀 含义 全称
+ 公有 public
- 私有 private
# 保护 protected
~ 包内 package / internal
classDiagram
    class User {
        +String id
        -String password
        #String email
        ~login() bool
    }
classDiagram class User { +String id -String password #String email ~login() bool }

4.2 关系 #

箭头方向是「从左到右读」:A <|-- B 表示 B 继承 A。需要时可以在关系后面加 : 标签。

语法 关系类型
`A < -- B` 继承(B 继承 A)
`A < .. B` 实现
A *-- B 组合(强拥有,B 随 A 销毁)
A o-- B 聚合(弱拥有,B 可独立存在)
A --> B 关联
A ..> B 依赖
A -- B 普通连接
classDiagram
    class 鸟
    class 翅膀
    class 汽车
    class 引擎
    class 人
    class 手机

    鸟 o-- 翅膀 : 有
    汽车 *-- 引擎 : 包含
    人 --> 手机 : 使用
classDiagram class 鸟 class 翅膀 class 汽车 class 引擎 class 人 class 手机 鸟 o-- 翅膀 : 有 汽车 *-- 引擎 : 包含 人 --> 手机 : 使用

5. 状态图(State Diagram) #

状态图用来画对象在不同状态之间如何跳转。使用 stateDiagram-v2 声明。[*] 表示起点或终点,边上的文字是触发跳转的事件。

stateDiagram-v2
    [*] --> 空闲
    空闲 --> 运行 : 启动
    运行 --> 暂停 : 暂停
    暂停 --> 运行 : 继续
    运行 --> 空闲 : 停止
    空闲 --> [*]
    运行 --> [*] : 关闭
stateDiagram-v2 [*] --> 空闲 空闲 --> 运行 : 启动 运行 --> 暂停 : 暂停 暂停 --> 运行 : 继续 运行 --> 空闲 : 停止 空闲 --> [*] 运行 --> [*] : 关闭

5.1 复合状态 #

一个状态内部还可以再套一层状态机,用 state 名称 { ... } 包起来。内层同样用 [*] 表示进入和离开。

stateDiagram-v2
    [*] --> 主状态
    state 主状态 {
        [*] --> 子状态1
        子状态1 --> 子状态2 : 事件
        子状态2 --> [*]
    }
    主状态 --> [*]
stateDiagram-v2 [*] --> 主状态 state 主状态 { [*] --> 子状态1 子状态1 --> 子状态2 : 事件 子状态2 --> [*] } 主状态 --> [*]

5.2 并发状态 #

复合状态里用 -- 分成上下两块,表示这两条状态线同时进行。

stateDiagram-v2
    [*] --> 并发
    state 并发 {
        [*] --> 状态A
        --
        [*] --> 状态B
    }
    并发 --> [*]
stateDiagram-v2 [*] --> 并发 state 并发 { [*] --> 状态A -- [*] --> 状态B } 并发 --> [*]

6. ER 图(Entity Relationship Diagram) #

ER 图用来画实体和它们之间的关系,常见于数据库设计。使用 erDiagram 声明。实体名建议用大写英文;字段可以标注 PK(主键)、FK(外键)、UK(唯一)。

erDiagram
    CUSTOMER ||--o{ ORDER : 下单
    ORDER ||--|{ ORDER_ITEM : 包含
    PRODUCT ||--o{ ORDER_ITEM : 被购买

    CUSTOMER {
        int id PK
        string name
        string email
    }
    ORDER {
        int id PK
        int customer_id FK
        date order_date
    }
    PRODUCT {
        int id PK
        string name
        float price
    }
    ORDER_ITEM {
        int id PK
        int order_id FK
        int product_id FK
        int quantity
    }
erDiagram CUSTOMER ||--o{ ORDER : 下单 ORDER ||--|{ ORDER_ITEM : 包含 PRODUCT ||--o{ ORDER_ITEM : 被购买 CUSTOMER { int id PK string name string email } ORDER { int id PK int customer_id FK date order_date } PRODUCT { int id PK string name float price } ORDER_ITEM { int id PK int order_id FK int product_id FK int quantity }

6.1 关系基数 #

关系写成 实体A 左基数--右基数 实体B : 标签。左右各用两个字符,表示「这一侧最少几个、最多几个」。

符号 含义
` ` 恰好一个
`o ` 零或一个
` {` 一个或多个
o{ 零个或多个

读法示例:CUSTOMER ||--o{ ORDER 表示「一个客户对应零个或多个订单,一个订单恰好对应一个客户」。

erDiagram
    CUSTOMER ||--o{ ORDER : 下单
    ORDER ||--|{ ORDER_ITEM : 包含
erDiagram CUSTOMER ||--o{ ORDER : 下单 ORDER ||--|{ ORDER_ITEM : 包含

7. 甘特图(Gantt Chart) #

甘特图用来排项目进度。使用 gantt 声明。dateFormat 决定日期怎么写,section 用来分组,任务写成 任务名 :修饰符, id, 开始, 时长。

gantt
    title 项目计划
    dateFormat YYYY-MM-DD
    section 设计阶段
    需求分析      :a1, 2024-01-01, 7d
    系统设计      :a2, after a1, 5d
    section 开发阶段
    前端开发      :b1, 2024-01-15, 10d
    后端开发      :b2, 2024-01-15, 10d
    测试          :c1, after b1 b2, 5d
    section 里程碑
    发布          :milestone, m1, 2024-02-01, 0d
gantt title 项目计划 dateFormat YYYY-MM-DD section 设计阶段 需求分析 :a1, 2024-01-01, 7d 系统设计 :a2, after a1, 5d section 开发阶段 前端开发 :b1, 2024-01-15, 10d 后端开发 :b2, 2024-01-15, 10d 测试 :c1, after b1 b2, 5d section 里程碑 发布 :milestone, m1, 2024-02-01, 0d

7.1 任务语法 #

冒号后面的字段用逗号分隔,顺序一般是「状态, id, 开始, 时长」。时长单位:d 天、w 周、h 小时。

写法 含义
任务名 :id, 开始日期, 时长 最简形式
after id 等某个任务结束后开始
after id1 id2 等多个任务都结束后开始
done 已完成
active 进行中
crit 关键路径
milestone 里程碑(通常时长写 0d)
gantt
    dateFormat YYYY-MM-DD
    section 任务
    已完成任务 :done, t1, 2024-01-01, 3d
    进行中任务 :active, t2, after t1, 5d
    关键任务   :crit, t3, after t2, 4d
    普通任务   :t4, after t3, 3d
gantt dateFormat YYYY-MM-DD section 任务 已完成任务 :done, t1, 2024-01-01, 3d 进行中任务 :active, t2, after t1, 5d 关键任务 :crit, t3, after t2, 4d 普通任务 :t4, after t3, 3d

8. 饼图(Pie Chart) #

饼图用来看占比。使用 pie 声明,title 写在同一行。每一项是 "名称" : 数值,Mermaid 会按数值自动算百分比。加上 showData 会在标签里同时显示原始数值。

pie title 水果占比
    "苹果" : 30
    "香蕉" : 20
    "橙子" : 25
    "葡萄" : 15
    "其他" : 10
pie title 水果占比 "苹果" : 30 "香蕉" : 20 "橙子" : 25 "葡萄" : 15 "其他" : 10

9. 用户旅程图(User Journey) #

用户旅程图用来画用户在各步骤上的体验。使用 journey 声明。每一行是 任务名 : 分数: 角色,分数 1~5,5 最满意。多个角色用逗号分隔。

journey
    title 用户购物旅程
    section 浏览商品
        打开网站 : 5: 用户
        搜索商品 : 4: 用户
        查看详情 : 4: 用户
    section 购买
        加入购物车 : 5: 用户
        结算支付 : 3: 用户
        完成订单 : 5: 用户, 系统
journey title 用户购物旅程 section 浏览商品 打开网站 : 5: 用户 搜索商品 : 4: 用户 查看详情 : 4: 用户 section 购买 加入购物车 : 5: 用户 结算支付 : 3: 用户 完成订单 : 5: 用户, 系统

10. 思维导图(Mindmap) #

思维导图按缩进表示层级。使用 mindmap 声明,需要 Mermaid 9.3 及以上。根节点常用 ((文字)) 画成圆形,其余节点靠空格缩进即可。

mindmap
  root((中心主题))
    分支1
      子分支1
      子分支2
    分支2
      子分支3
      子分支4
    分支3
mindmap root((中心主题)) 分支1 子分支1 子分支2 分支2 子分支3 子分支4 分支3

11. 时间线(Timeline) #

时间线用来按时间列出事件。使用 timeline 声明。同一年有多件事时,在该年份下再写若干 : 事件。

timeline
    title 历史时间线
    2020 : 项目启动
    2021 : 产品发布
    2022 : 用户突破百万
    2023 : 国际化扩张
    2024 : 上市
timeline title 历史时间线 2020 : 项目启动 2021 : 产品发布 2022 : 用户突破百万 2023 : 国际化扩张 2024 : 上市

12. 其他图表 #

下面几类不如流程图、时序图常用,语法也更短。需要时再查官方文档即可。部分关键字带 -beta,旧版渲染器可能不支持。

图表类型 关键字 说明
Git 图 gitGraph 展示 Git 分支与提交
象限图 quadrantChart 四象限分析
需求图 requirementDiagram 需求之间的关系
XY 图 xychart-beta 折线 / 柱状图
桑基图 sankey-beta 流量从哪来、到哪去

12.1 Git 图 #

commit 在当前分支记下一次提交,branch / checkout 切换分支,merge 把另一条分支合进来。

gitGraph
    commit id: "init"
    commit id: "feat"
    branch develop
    checkout develop
    commit id: "dev-1"
    checkout main
    merge develop
    commit id: "release"
gitGraph commit id: "init" commit id: "feat" branch develop checkout develop commit id: "dev-1" checkout main merge develop commit id: "release"

12.2 象限图 #

四个象限各自有标题。数据点写成 名称: [x, y],坐标范围是 0~1。

quadrantChart
    title 功能优先级
    x-axis 低投入 --> 高投入
    y-axis 低价值 --> 高价值
    quadrant-1 尽快做
    quadrant-2 规划做
    quadrant-3 可砍掉
    quadrant-4 有空再做
    登录: [0.2, 0.8]
    报表导出: [0.7, 0.6]
    皮肤主题: [0.8, 0.2]
quadrantChart title 功能优先级 x-axis 低投入 --> 高投入 y-axis 低价值 --> 高价值 quadrant-1 尽快做 quadrant-2 规划做 quadrant-3 可砍掉 quadrant-4 有空再做 登录: [0.2, 0.8] 报表导出: [0.7, 0.6] 皮肤主题: [0.8, 0.2]

13. 使用提示 #

  1. 节点 ID 建议用英文或拼音,显示文本用中文。ID 里一旦出现空格或特殊符号,解析很容易出错。
  2. 注释用 %%,在流程图、时序图、类图里都有效。
  3. 显示文本里尽量避开 ()、{}、[]。必须写的时候用引号包起来,例如 A["含(括号)的文本"]。
  4. 不同平台的 Mermaid 版本不一样。GitHub、Notion、VS Code 插件各自绑的版本不同,新语法(带 -beta 的、思维导图)可能在部分平台画不出来。
  5. 图不显示时先查这三处:括号有没有配对、箭头方向有没有写反、关键字有没有拼错。
  6. 样式:流程图和甘特图支持的定制最多,时序图、饼图能改的很少。

Mermaid 语法短、能直接写在 Markdown 里。先把流程图和时序图练熟,其余图表按需查本节即可。