Please enable Javascript to view the contents

Graphviz 工具包 DOT 绘图

 ·  ☕ 3 分钟

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 通用属性

属性名称默认值含义
colorblack颜色
colorschemeX11颜色描述
fontcolorblack文字颜色
fontnameTimes-Roman字体
fontsize14文字大小
label显示的标签,对于节点默认为节点名称
penwidth1.0线条宽度
style样式
weight重要性

2.3 图的属性

属性名称默认值含义
bgcolor背景颜色
concentratefalse让多条边有公共部分
nodesep.25节点之间的间隔(英寸)
peripheries1边界数
ranksame,min,source, max,sink,设置多个节点顺序
rankdirTB排序方向
ranksep.75间隔
size图的大小(英寸)

2.4 节点属性

属性名称默认值含义
shapeellipse形状
sides4当shape=polygon时的边数
fillcolorlightgrey/black填充颜色
fixedsizefalse标签是否影响节点的大小

2.5 边属性

属性名称默认值含义
arrowheadnormal箭头头部形状
arrowsize1.0箭头大小
arrowtailnormal箭头尾部形状
constrainttrue是否根据边来影响节点的排序
decorate设置之后会用一条线来连接edge和label
dirforward设置方向:forward,back,both,none
headcliptrue是否到边界为止
tailcliptrue与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>
  • 利用gcode标签,插入DOT脚本
 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/

微信公众号
作者
微信公众号