技术拆解-Mermaid
运行
npm run dev:vite
绘图
饼图
D3.js 可以参考饼图的代码: mermaid/packages/mermaid/src/diagrams/pie/pieRenderer.ts
flowchart
D3.js + Dagre
mindmap
Cytoscape + D3.js 布局用的 Cytoscape 画图用的 D3.js
草图风格 Rough
代码结构
- spec.ts:使用 Jest 框架编写的单元测试文件,主要用于测试 pie 模块的功能
- Db.ts:数据管理,各种 add、set、get 方法
- Detector.ts:识别 pie 的文本,并 import pieDiagram.js
- Diagram.ts:对外的 Facade,包含了 Db、Renderer、Parser、Styles 等
- Parser.ts:AST 解析文本为 Pie 对象
- Renderer.ts:绘图
- Styles.ts:样式 Token
- Types.ts:类型定义
数据结构
图表
基类
/**
* Generic Diagram DB that may apply to any diagram type.
*/
export interface DiagramDB {
// config
getConfig?: () => BaseDiagramConfig | undefined;
// db
clear?: () => void;
setDiagramTitle?: (title: string) => void;
getDiagramTitle?: () => string;
setAccTitle?: (title: string) => void;
getAccTitle?: () => string;
setAccDescription?: (description: string) => void;
getAccDescription?: () => string;
setDisplayMode?: (title: string) => void;
bindFunctions?: (element: Element) => void;
}
Pie
export interface PieDB extends DiagramDB {
// config
getConfig: () => Required<PieDiagramConfig>;
// common db
clear: () => void;
setDiagramTitle: (title: string) => void;
getDiagramTitle: () => string;
setAccTitle: (title: string) => void;
getAccTitle: () => string;
setAccDescription: (description: string) => void;
getAccDescription: () => string;
// diagram db
addSection: ({ label, value }: D3Section) => void;
getSections: () => Sections;
setShowData: (toggle: boolean) => void;
getShowData: () => boolean;
}
draw()
/**
* Type for function draws diagram in the tag with id: id based on the graph definition in text.
*
* @param text - The text of the diagram.
* @param id - The id of the diagram which will be used as a DOM element id.
* @param version - MermaidJS version from package.json.
* @param diagramObject - A standard diagram containing the DB and the text and type etc of the diagram.
*/
export type DrawDefinition = (
text: string,
id: string,
version: string,
diagramObject: Diagram
) => void | Promise<void>;
布局 Layout
协议
flowchart
样式是在末尾定义的,给每个节点定义的样式,通过节点的 ID(比如 A、B、C)进行绑定。 感觉这样定义,表现力并不强?而且一些复杂的效果估计不好描述。 动画怎么描述?
flowchart LR
subgraph subgraph_zv2q8ucnp["Shape descriptions"]
customer(("Customer"))
Support["Support"]
Technician{{"Technician"}}
Decision{"Decision"}
end
A(("Reported issue")) --> B["Ticket is created"]
B --> C{"Working hours?"}
C -- Yes --> E{{"Tickets are sent to day team for response"}}
C -- No --> F["Tickets are sent to on-call staff for response"]
E --> Worked{"Ticket being worked on?"}
F --> Worked
Worked -- Yes --> G["Work on the tickets based on priority"]
Worked -- No --> Reminder["Reminder is sent"]
Reminder --> Worked
G --> H["Team fixes the issue"]
H --> I{"Is the issue resolved?"}
I -- Yes --> Done["Ticket is closed and follow-up email is sent"]
I -- No --> H
customer:::redNode
Support:::pinkNode
Technician:::yellowNode
Decision:::blackNode
A:::redNode
C:::blackNode
E:::yellowNode
F:::pinkNode
Worked:::reminderNode
G:::pinkNode
H:::pinkNode
I:::reminderNode
Done:::greenNode
classDef redNode fill:#D50000,color:#000000
classDef pinkNode fill:#E1BEE7,color:#000000
classDef yellowNode fill:#FFF9C4,color:#000000
classDef blackNode fill:#000000,stroke:#FFD600,stroke-width:4px,stroke-dasharray: 0,color:#FFFFFF
classDef greenNode fill:#00F840,color:#000000
classDef reminderNode stroke:#FFD600,stroke-width:4px,stroke-dasharray: 0,fill:#000000,color:#FFFFFF
classDef blueSubgraph fill:#BBDEFB
style A stroke:#2962FF,fill:#AA00FF
style C fill:#00C853
linkStyle 2 stroke:#00C853,fill:none
linkStyle 3 stroke:#D50000,fill:none
linkStyle 6 stroke:#00C853,fill:none
linkStyle 7 stroke:#D50000,fill:none
linkStyle 11 stroke:#00C853,fill:none
linkStyle 12 stroke:#D50000,fill:none
Takeaways
为什么节点要展平成平铺的 g 结构:增加可编辑性
类似 Photoshop,层的概念,可以任意移动布局。 因此带有编辑概念的(Mermaid、Napkin),都是这样的平铺结构。
日志
log.info('REF0:');
不足
缺少动画
缺少 timeline 播放
资料
github: https://github.com/mermaid-js/mermaid
在线编辑器: https://github.com/mermaid-js/mermaid-live-editor
mermaidchart: https://www.mermaidchart.com/ 这个是企业版,支持了拖拽布局、AI、画布、节点样式编辑等功能。 其中画布、节点样式编辑目前仅支持 Flowchart 和 Sequence Diagram。