by: uizuizui
Dot是开源工具包Graphviz上用来画图的一门脚本语言。通过布局引擎解析脚本得到图像,然后可以将图像导出为各种格式以满足需求。有了它,我们就可以很方便地通过编写脚本来画各种结构示意图和流程图。
Graphviz的文件后缀名为.gv。每个.gv文件代表一个图,我们可以通过dot -Tpng example.dot -o example.png
命令行方式生成图像,或者使用Graphviz提供的工具gvedit来编辑和运行脚本。
Dot脚本的语法非常简单,官方文档只有8页。花一点点时间学习,就可以掌握。下面介绍Dot脚本一些比较常用的语法。
使用digraph graph_name
可以声明一个图,而图的具体实现代码则由一对花括号包含起来。
digraph graph1 {
//something
}
当图中某些内容同属一个类别时,我们可以声明一个子图将其包含在一起。使用subgraph cluster_subgraph_name
可以在声明一个子图。
注意:子图的名字必须以cluster开始,否则解析引擎无法进行识别
subgraph cluster_subgraph1 {
// something
}
下面我们来看一个具体例子:
digraph example1 {
label = "this is a graph";
a;b;
subgraph cluster_sgh {
label = "this is subgraph";
bgcolor = greenyellow;
c;d;
}
}
抛开那些还没讲到的语法。可以看到,这里布局引擎将子图里的c和d结点聚合在了一起,这在某些场景下是非常有用的,可以将逻辑上相近的内容放在一起显示。
Dot里结点的声明十分简单。键入结点名字node_name;
即可声明一个结点,同时,结点默认的显示内容就是结点名字。
当结点内容里面有空格时,我们可以将结点名字用一对双引号包含起来,解析引擎会直接取双引号里面的内容创建结点。
使用符号->可以声明一条边。a -> b
就代表一条由结点a连接到结点b的边。结点可以连接到结点自身
a;
b;
a -> b;
如果不需要对结点进行单独的属性设置(后面讲解),则可以直接声明边,解析引擎会自动创建相应的结点。
a -> b;
声明多条边的便捷语法:
a; b; c;
a -> b -> c -> c;
图的属性设置可以写在graph []
里,或者直接写在外面:
digraph graph1 {
bgcolor = red;
graph [bgcolor = red];
}
图的属性包括:
bgcolor:设置图的背景颜色,可以使用red、blue、green等形式,或者使用"#rrggbb"
形式。
label:设置图的描述。label会继承到子图,子图里如果不想重复显示必须手动设置
rankdir:设置图的方向,包括:TB(top to bottom)、BT(bottom to top)、LR(left to right)、RL(right to left)。
rotate:设置图的旋转。如:rotate = 90
便是逆时针旋转90度。
ratio:设置图的长宽比,可以是一个浮点数,也可以是:fill、compress或者auto。
结点和边的属性设置非常简单,只需要在结点或者边的声明后面加上方括号,然后在方括号里填写属性键值对即可。键值对之间使用逗号进行分割。
a [shape = egg, label = "this is node a"];
b [shape = circle, label = "this is node b"];
a -> b [style = dashed, label = "this is edge a to b"];
结点的常用属性:
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:设置结点高度。
peripheries:设置结点边框个数。
fontcolor:设置结点内容颜色。可以使用单词形式或者"#rrggbb"
形式。
需要重点强调的是:
如果设置了style = filled,此时设置的color是代表整体颜色。
但是如果设置了fillcolor再设置color的话,color代表边框颜色。
边的常用属性:
style:设置边的形状。包括:solid(实线)、dashed(虚线)、dotted(点线)、bold(加粗)、invis(隐形)。
label:设置边标签。内容用双引号包含,可以使用转义字符。
color:设置边颜色。可以使用单词形式或者"#rrggbb"
形式。
arrowhead:设置结点箭头样式。包括:none、empty、odiamond等。
使用node []
和edge []
可以分别设置结点和边的全局设置:
digraph graph1 {
node [shape = egg];
edge [style = dashed];
a -> b;
}
Graphviz默认是不支持中文的,输入的中文在生成的图中显示为一个空方块。如果想要让其支持中文,可以尝试以下方法:
方法一:在命令行里指定-Nfontname=xxx.ttf
,在gv文件中输入utf-8编码的汉字。
方法二:给graph、node和edge均设置fontname = xxx.ttf
然后设置label。
前面提到record和box有所区别。原因就是:设置为record和Mrecord的结点的label属性可以很方便地生成单列的表格和UML图等。(类似于XAML里面的stack)
用一对双引号+一对花括号包含起来的就是表格内容,不同的格子之间用符号 | 隔开,尖括号里的内容表示一个锚点(具体讲解见下文)。
example [ shape = record, label = "{cell1 | cell2 | cell3}" ];
也可以生成空格只保留锚点:
label="{
如果record生成的表格不符合预期,还可以使用html标签生成表格。只需要将结点的label属性设置为相应的html代码(用一对尖括号包含)即可。
table1 [label=<
<table>
<tr>
<td port="one">1td>
<td>2td>
tr>
<tr>
<td>3td>
<td>4td>
tr>
table>
>];
port属性可以为td增加一个锚点。
cell的锚点可以让使用者在cell之间画线。
引用cell的锚点的语法为:table: anchor_name
示例代码:
digraph example2 {
node [shape = record];
table1 [label = "{cell1 | cell2 | cell3}"];
table2 [label = "{cell1 | cell2}"];
table1: head -> table2: head;
}
我们还可以巧妙地使用结点的某些属性来生成图形。如:
circle [label="", shape="circle", width=0.5, fixedsize=true, style=filled, color=black];
就生成了一个实心黑色圆形。
不仅可以使用代码里的全局设置,还可以在命令行里进行全局设置,这样做的好处就是可以根据不同要求来生成图形。
dot -Grankdir=LR -Nshape="plaintext" -Earrowhead="odiamond" -Tpng example.dot -o example.png
Grankdir即 graph rankdir
Nshape即 node shape
Earrowhead即 edge arrowhead
其他的属性均按照这种规则进行填写。
Dot的注释使用//(单行)或者/**/(多行)。
// 这是单行注释
/*
这是多行注释
*/
最后,关于graphviz结点的布局:
graphviz的节点出现在画布上的位置事实上是不确定的,依赖于所使用的布局算法,而不是在脚本中出现的位置,这可能使刚开始接触graphviz的开发人员有点不适应。graphviz的强项在于自动布局,当图中的顶点和边的数目变得很多的时候,才能很好的体会这一特性的好处。
以上部分内容引用自:
http://www.cnblogs.com/CoolJie/archive/2012/07/17/graphviz.html
http://wiki.woodpecker.org.cn/moin/GraphViz
感谢内容提供者