1. 简介
Graphviz是贝尔实验室开发的一个开源的绘图工具包。它使用一个特定的DSL(领域特定语言): DOT作为脚本语言。使用布局引擎来解析DOT脚本,完成自动布局。支持丰富的导出格式,例如:PNG、JPG、PostScript、SVG、PDF等。
支持的布局引擎:
- dot 默认布局方式,主要用于有向图
- neato 基于spring-model(又称force-based)算法布局
- twopi 放射状布局
- circo 圆环布局
- fdp 无向图布局
编译命令为:
1
| <cmd> <inputfile> -T <format> -o <outputfile>
|
其中Graphviz 的 cmd 有好几种,每种使用方法都完全相同,差别只在于渲染出来的图片效果不一样。cmd可选项[dot、neato、twopi、circo、fdp],也就是上面的布局引擎。
使用 dot 命令编译,如
1
| dot hello.dot -T png -o hello.png
|
2. DOT语法特征
DOT语法相对简单,没有特殊的格式要求,也没有复杂的运算符和结构。Graphviz图形主要由节点、边、标注组成。
2.1 语法关键字
- 注释,使用//注释
- 有向图 - 使用digraph定义有向图
- 有向图 - 使用->表述节点之间的关系
- 无向图 - 使用graph定义无向图
- 无向图 - 使用 – 表述节点之间的关系
- 节点之间的关系 - 有向图:a -> b,a节点指向b节点
- 节点之间的关系 - 无向图:a – b, a节点与b节点连通
- 定义节点属性 - 格式为: node[attribute1=value1, attribute2=value2]
- 子图 - 使用subgraph定义子图
2.2 通用属性
属性名称 | 默认值 | 含义 |
---|
color | black | 颜色 |
colorscheme | X11 | 颜色描述 |
fontcolor | black | 文字颜色 |
fontname | Times-Roman | 字体 |
fontsize | 14 | 文字大小 |
label | | 显示的标签,对于节点默认为节点名称 |
penwidth | 1.0 | 线条宽度 |
style | | 样式 |
weight | | 重要性 |
2.3 图的属性
属性名称 | 默认值 | 含义 |
---|
bgcolor | | 背景颜色 |
concentrate | false | 让多条边有公共部分 |
nodesep | .25 | 节点之间的间隔(英寸) |
peripheries | 1 | 边界数 |
rank | | same,min,source, max,sink,设置多个节点顺序 |
rankdir | TB | 排序方向 |
ranksep | .75 | 间隔 |
size | | 图的大小(英寸) |
2.4 节点属性
属性名称 | 默认值 | 含义 |
---|
shape | ellipse | 形状 |
sides | 4 | 当shape=polygon时的边数 |
fillcolor | lightgrey/black | 填充颜色 |
fixedsize | false | 标签是否影响节点的大小 |
2.5 边属性
属性名称 | 默认值 | 含义 |
---|
arrowhead | normal | 箭头头部形状 |
arrowsize | 1.0 | 箭头大小 |
arrowtail | normal | 箭头尾部形状 |
constraint | true | 是否根据边来影响节点的排序 |
decorate | | 设置之后会用一条线来连接edge和label |
dir | forward | 设置方向:forward,back,both,none |
headclip | true | 是否到边界为止 |
tailclip | true | 与headclip类似 |
3. 实例
3.1 流程图
digraph G {
subgraph cluster_0 {
node [style=filled,color=yellow]; //设置节点属性
edge [color = "green", decorate = false]; //设置边属性
a0 -> a1;//连接信息
label = "#1";//标签
}
subgraph cluster_1 {
node [style=filled];
b0 -> b1;
label = "#2";
}
start -> {a0,b0};
{a1,b1} -> end;
start [shape=Mdiamond];//设置节点图形
end [shape=Msquare];
}
3.2 结构图
digraph G {
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf;
init -> make_string;
main -> printf;
execute -> compare;
}
3.3 数据结构图
digraph g {
node [shape = record,height=.1];
node0[label = "<f0> |<f1> G|<f2> "];
node1[label = "<f0> |<f1> E|<f2> "];
node2[label = "<f0> |<f1> B|<f2> "];
node3[label = "<f0> |<f1> F|<f2> "];
node4[label = "<f0> |<f1> R|<f2> "];
node5[label = "<f0> |<f1> H|<f2> "];
node6[label = "<f0> |<f1> Y|<f2> "];
node7[label = "<f0> |<f1> A|<f2> "];
node8[label = "<f0> |<f1> C|<f2> "];
"node0":f2 -> "node4":f1;
"node0":f0 -> "node1":f1;
"node1":f0 -> "node2":f1;
"node1":f2 -> "node3":f1;
"node2":f2 -> "node8":f1;
"node2":f0 -> "node7":f1;
"node4":f2 -> "node6":f1;
"node4":f0 -> "node5":f1;
}
4. 前端集成
前端整合 Graphviz,主要是通过 Viz.js,将文本内容转化为图片,然后动态添加到页面实现的。这里有一段 JavaScript,获取标签的文本内容,并在标签同一级插入 Viz.js 生成的图片。
1
2
3
4
5
6
7
8
9
| <script src="https://cdn.bootcss.com/viz.js/1.8.0/viz.js"></script>
<script>
// add graphviz support
$('.gcode').each(function(){
var gcodeNode = document.createElement('span');
gcodeNode.innerHTML = Viz(this.innerText);
this.append(gcodeNode );
});
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <p><script type="text/vnd.graphviz" class="gcode">
graph G {
e
subgraph clusterA {
a -- b;
subgraph clusterC {
C -- D;
}
}
subgraph clusterB {
d -- f
}
d -- D
e -- clusterB
clusterC -- clusterB
}
</script></p>
|
5. 参考
- 1.http://www.graphviz.org/Download.php
- 2.https://zh.wikipedia.org/zh-hans/Graphviz
- 3.https://github.com/mdaines/viz.js/
- 4.http://viz-js.com/