Graphviz概述
Graphviz
是一个由AT&T实验室启动的使用DOT语言来绘制关系图/流程图的开源工具包。
DOT
语言是一种文本图形描述语言,它提供了一种简单的描述图形的方法。
使用Graphviz,我们只需要将精力集中在逻辑设计上,而不需要花费大量时间在图形布局的调整上,图形绘制布局都由工具引擎来搞定。也因此,需要精确定位的图形就不适合用Graphviz来绘制了。另外,文本代码绘制图形的方式也便于版本管理。
另外,
plantuml
也包含了dot语法,并且还具有更多的功能,或许你可以尝试一下。
Graphviz工具
工具善其事,必先利其器。原谅我是一个工具痴 :-)
要想使用graphviz,首先需要上官网下载graphviz并安装。安装之后就可以使用graphviz自带的编辑器gvedit
来编写dot代码来绘制图形了。快捷键F5
来预览生成的图片,Shift+F5
打开对话框并点击ok就可以生成指定类型的图片文件。
但是graphviz自带的gvedit编辑器那是非常非常的难用。怎么办呢?经过四处寻找和妥协,最终找到了windows平台下的还挺好用的工具,此工具不仅具有dot代码高亮、代码提示,还阔以预览生成的图片,只是暂时还不能导出图片。该工具就是github出品的代码编辑器Atom,另外需要安装两个插件:language-dot和graphviz-preview。
使用Atom来编写和预览图片,最后使用gvedit来导出图片。看起来还不错的样子。
- windows中安装好graphviz之后,最好配置一下
PATH
环境变量。
- Atom的language-dot插件中的代码提示模板(snippet)可能不能满足你的需求,不过你可以自己添加和修改。这里有我自己修改的代码模板。
中文乱码解决
若渲染出的图片中出现乱码,检查两项:
-
文件编码需要使用utf-8。
-
windows平台下需要在dot源码中指定字体名称。具体如下:
// 影响图片级别的字体 graph [fontname="宋体"]; // 影响节点中的文字字体 node [fontname="宋体"]; // 影响箭头或线条上的文字字体 edge [fontname="宋体"];
DOT基本语法
DOT语法相对简单和松散,没有特别的格式要求,也没有复杂的运算符和结构。你可以查看官方文档以了解更多,其实安装完graphviz后,其安装目录中就有文档了,位置如下:
GRAPHVIZ_HOME/share/graphviz/doc/html/index.html
|
概述
- DOT中使用图(
digraph
/graph
)、节点(node
)和边(edge
)来描述关系图/流程图。
- DOT的注释风格和C类似(
//
用于单行注释,/* */
用于多行注释)。
图
DOT可以描述有向图(使用digraph
声明)和无向图(使用graph
声明)两种图。图由{}
中包含的节点和边构成。
在图的开头使用graph []
对图进行设置,如:graph [bgcolor="gray"]
将图背景色设置为灰色。属性设置语句也可以不包含在graph []
中而直接使用。
子图(使用subgraph
声明)可以进行和“父图”类似的设置,唯一注意的是子图必须以cluster
做为名称的前缀。
节点
DOT中,节点可以不用声明直接使用,但如果需要设置节点的属性,则需声明节点并在声明处设置属性然后再使用。每个节点首次出现的名称做为该节点的唯一标识。
node []
用于设置节点默认属性(对设置位置之后的点有效),在节点后面用[]
设置单独一个点的属性。
边
DOT中有有向边(使用->
表示)和无向边(使用--
表示)两种,有向边用于有向图,无向边用于无向图,不可混用。
和节点类似的,用edge []
设置边默认属性,在边之后用[]
设置单独一条边的属性。对于有向边,还可以设置边的起点/终点的位置(用n、e、s、w或它们的组合表示位置)。
常用属性
对于各种结构的通用属性如下:
属性名称 | 默认值 | 含义 |
---|---|---|
color | black | 颜色,颜色设置支持形如red 和#FF0000 两种形式 |
fontcolor | black | 文字颜色 |
fontname | Times-Roman | 字体 |
fontsize | 14 | 文字大小 |
label | 显示的标签,支持’\n’换行,对于节点默认为节点名称 | |
penwidth | 1.0 | 线条宽度 |
style | 样式 |
常用图属性如下:
属性名称 | 默认值 | 含义 |
---|---|---|
bgcolor | 背景颜色 | |
concentrate | false | 让多条边有公共部分 |
nodesep | .25 | 节点之间的间隔(英寸) |
peripheries | 1 | 边界数 |
rank | same,min,source, max,sink,设置多个节点顺序 | |
rankdir | TB | 排序方向 |
ranksep | .75 | 间隔 |
size | 图的大小(英寸) | |
labelloc | 调整图或子图的标签的上下位置 | |
labeljust | 调整图或子图的标签的左右位置 | |
compound | false | If true, allow edges between clusters. 配合lhead 和ltail 使用 |
常用节点属性如下:
属性名称 | 默认值 | 含义 |
---|---|---|
shape | ellipse | 形状 |
sides | 4 | 当shape=polygon时的边数 |
fillcolor | lightgrey/black | 填充颜色 |
fixedsize | false | 标签是否影响节点的大小 |
常用边属性如下:
属性名称 | 默认值 | 含义 |
---|---|---|
arrowhead | normal | 箭头头部形状 |
arrowsize | 1.0 | 箭头大小 |
arrowtail | normal | 箭头尾部形状 |
constraint | true | 是否根据边来影响节点的排序 |
decorate | 设置之后会用一条线来连接edge和label | |
dir | forward | 设置方向:forward,back,both,none |
headclip | true | 是否到边界为止 |
tailclip | true | 与headclip类似 |
headlabel | 边的头部显示的标签 | |
taillabel | 边的尾部显示的标签 | |
lhead | 当compound 为true时,lhead用于指定边指向的cluster |
|
ltail | 与ltail类似 |
简单示例
dot代码:
digraph simple_demo {
// 设置图、节点和边的默认属性
graph [label="simple demo", bgcolor="#EEEEEE"];
node [style="filled", fillcolor="#AAAAAA"];
edge [style="dashed", arrowsize=0.6];
// 节点和边
{a, b} -> {c, d};
}
|
图片效果:
高级用法
绘制二叉树
绘制二叉树使用到了记录形式的节点,代码如下:
digraph g {
node [shape="record", height=.1];
node0[label=" |
其中,用|
隔开的串会在绘制出来的节点中展现为一条分隔符,用<>
括起来的串称为锚点。
效果如下:
竖排记录
记录形式的节点也可以是竖形排列的。与横向排列的记录的不同只是label的形式不同,label中内容使用{}
包围则是竖形排列的。代码如下:
digraph g {
node [shape="record"];
a [label="{a | b | c}"];
}
|
效果如下:
自定义复杂节点
label还支持HTML格式的,这样你能想得到的大部分样子的节点都可以被自定义出来。代码如下:
digraph html {
abc [shape=none, margin=0, label=<
|
效果如下:
直接指向cluster
边直接指向cluster,需要设置compound
为true,并配合lhead
或ltail
来实现。代码如下:
digraph G {
compound=true;
subgraph cluster0 {
a;
}
subgraph cluster1 {
b;
}
a -> b [lhead=cluster1];
}
|
效果如下:
简单的时序图
简单的时序图代码如下:
digraph g {
rankdir="LR";
{
rank="same";
a0 -> a1 -> a2;
}
{
rank="same";
b0 -> b1 -> b2;
}
a1 -> b1;
}
|
其中,rankdir="LR"
表示,布局从左L
到右R
,每一个rank="same"
的block中的所有节点都会在同一条线(横线或竖线)上。
效果如下:
以图片为节点
节点还可以使用图片,通过在节点中使用image="image_path"
来设置图片。不过需要注意的是,在使用图片作为节点的时候,需要将本来的形状设置为none
,并且将label
置为空字符串,避免出现文字对图片的干扰。
Graphviz编程库
-
Python:PyGraphviz
-
Java:graphviz-java-api