1.简介
dot是开源工具包Graphviz上用来画图的一门脚本语言。通过布局引擎解析脚本得到图像,然后可以将图像导出为各种格式以满足需求。主要用于编写脚本来画各种结构示意图和流程图。
Graphviz的文件后缀名是.gv
。每个.gv
文件代表一个图,可以通过dot -Tpng example.gv -o example.png
命令生成图像,或者使用Graphviz提供的工具gvedit来编辑和运行脚本。
dot脚本的语法特别简单,官方doc只有8页。下面简单介绍下dot脚本的一些语法。
2.图的声明
使用digraph graphName
可以申明一个图,具体实现代码用一对花括号包裹起来。
1 | digraph graph1 { |
当图中某些内容同属一个类时,我们可以申明一个子图将其包含在齐齐。使用subgraph cluster_subgraphName
可以申明一个子图^1。
1 | subgraph cluster_subgraphName { |
来看一个具体的例子
1 | digraph example1 { |
3.结点和边的声明
dot里结点的申明非常简单,只需要键入结点名字nodeName
;同时,结点默认的现实内容为结点名字。
当结点内容有空格时,我们可以将结点用一堆双引号包含起来,解析引擎会直接提取双引号里面的内容创建结点。
使用符号->
就可以申明一条边,a -> b
就代表由结点a连接到结点b的边^2。结点也可以连接到结点自身。
1 | a; |
申明多条边的便捷语法:
1 | a; b; c; |
4.图的属性
图的属性可以写在graph[]
里,也可以直接写在外面:
1 | digraph graph1 { |
图的属性包括:
bgcolor
:设置图的背景颜色,可以使用rgb值,也可以用#rrggbb
编码形式label
:设置图的描述。label会继承到子图,如果不想子图重复label需手动设置rankdir
:设置图的方向,包括:TB(top to bottom)、BT(bottom to top)、LR(left to Right)、RL(right to left)rotate
:设置图的旋转。如rotata = 90
代表旋转90度,默认逆时针ratio
:设置图的长宽比,可以是一个浮点数,也可以是:fill、compress、auto
5.结点属性和边属性
结点和边的属性设置非常简单,只需要在结点或者边的声明后面加上方括号,然后在方括号里填写属性键值对即可。键值对之间使用逗号进行分割。
1 | a [shape = egg, label = "this is node a"]; |
结点的常用属性:
shape
:设置结点形状。包括:Mrecord(圆角矩形)、record(矩形)、circle(圆形)、box(矩形,和record略有区别,下面会讲到)、egg(蛋形)、doublecircle(双圆形)、plaintext(纯文本)、 ellipse(椭圆,默认)。label
:设置结点的显示内容,内容用双引号包含,可以使用转义字符。当结点内容!=结点名时使用style
:设置结点的样式。包括:filled(填充)、dotted(点状边框)、solid(普通边框)、dashed(虚线边框)、bold(边框加粗)、invis(隐形)。color
:设置边框颜色。可以使用单词形式或者#rrggbb
形式。fillcolor
:设置填充颜色,仅style = filled时有效。width
:设置结点宽度。height
:设置结点高度。perpheries
:设置结点边框个数。fontcolor
:设置结点内容颜色。可以使用单词形式或者#rrggbb
形式。
边的常用属性:
1.style
:设置边的形状。包括:solid(实线)、dashed(虚线)、dotted(点线)、bold(加粗)、invis(隐形)。
label
:设置边标签。内容用双引号包含,可以使用转义字符。color
:设置边颜色。可以使用单词形式或者#rrggbb
形式。arrowhead
:设置结点箭头样式。包括:none、empty、odiamond等。
使用node[]
和edge[]
可以分别设置结点和边的全局设置:
1 | digraph graph1{ |
6.其他应用
使dot支持中文
Graphviz默认是不支持中文的,输入的中文在生成的图中显示为一个空方块。如果想要让其支持中文,可以尝试以下方法:
- 在命令行制定
-Nfontname = xxx.ttf
,在gv文件中输入utf-8编码的汉字 - 给graph、node、edge设置
fontname = xxx.ttf
然后设置label
使用record的label属性生成表格
前面提到record和box有所区别。原因就是:设置为record和Mrecord的结点的label属性可以很方便地生成单列的表格和UML图等。(类似于XAML里面的stack)
用一对双引号+一对花括号包含起来的就是表格内容,不同的格子之间用符号 | 隔开,尖括号里的内容表示一个锚点
1 | example [shape = record, label = "{<head>cell1 | cell2 | cell3}"]; |
也可以生成空格只保留锚点:
1 | label="{<b1>|<b2>|<b3>}" |
使用html标签生成表格
如果record生成的表格不符合预期,还可以使用html标签生成表格。只需要将结点的label属性设置为相应的html代码即可。
1 | table1 [label=< |
port
属性可以给td
增加一个锚点
表格锚点的应用
cell的锚点可以让使用者在cell之间划线
引用cell的锚点的语法为table: anchorName
示例代码1
2
3
4
5
6
7digraph example2 {
node [shape = record];
table1 [label = "{<head>cell1 | cell2 | cell3}"];
table2 [label = "{<head>cell1 | cell2}"];
table1: head -> table2: head
}
生成图形
可以使用结点的某些属性来生成图形,如
1 | circle [label="", shape="circle", width=0.5, fixedsize=true, style=filled, color=black]; |
就生成了一个实心的黑色圆形。
命令行全局设置
不仅可以使用代码里的全局设置,还可以在命令行里进行全局设置,这样就可以根据不同要求来生成图形。
1 | dot -Grankdir=LR -Nshape="plaintext" -Earrowhead="odiamond" -Tpng example.dot -o example.png |
Grankdir
: graph rankdirNshape
: node shapeEarrowhead
: edge arrowhead
其他一些属性也可以按照这种规则填写
添加注释
dot的注释使用//
(单行)或者/* */
(多行)
7.几个实例
(1) 复杂的标签
1 | digraph structs{ |
1 | graph picture { |
(2) 行列对齐
1 | digraph html { |
(2)二叉树
1 | digraph G { |
(4)哈希表
1 | digraph G{ |
(5)流程图
1 | digraph G{ |
8.参考文献
- 啄木鸟社区关于GraphViz的文章:https://wiki.woodpecker.org.cn/moin/GraphViz
- Cnblog上的一篇文章:http://www.cnblogs.com/CoolJie/archive/2012/07/17/graphviz.html
- 简书上的dot学习笔记:http://www.jianshu.com/p/e44885a777f0
- dot官方文档:http://www.graphviz.org/pdf/dotguide.pdf
- CSDN上关于python实现graphviz的文章:http://blog.csdn.net/a1368783069/article/details/52067404