关于安装
你可以去Graphviz官方网站找到各个系统的下载方式,并且在官网有对这个软件更详细的说明。安装非常简单,只需要一路确认即可。
关于编译
你可以通过命令行快速得到渲染后的图像文件。命令如下:
cmd [ flags ] [ input files ]
cmd
为你想要使用的渲染方式,Graphviz提供的渲染方式有下列几种:
指令 | 介绍 |
---|---|
dot |
渲染的图具有明确方向性。 |
osage |
渲染的图是集群的矩形。 |
neato |
渲染的图缺乏方向性。 |
twopi |
渲染的图采用放射性布局。 |
circo |
渲染的图采用环型布局。 |
fdp |
渲染的图缺乏方向性。 |
sfdp |
渲染大型的图,图片缺乏方向性。 |
patchwork |
渲染如Treemaps的集群图表。 |
详细可以见官方说明。
[ flags ]
是想要加上的参数。
常见的有:
-T
: 设定输出的格式/后缀名。
-o
: 设定输出的文件名。
-O
: 根据输入的文件名输出文件,并且支持-T
多格式输出。
-s
: 指定一个特定的输出比例大小。
更多参数可以在官方文档查看。
如果你不想要这样麻烦的操作,这里有两种可能更好的方法:
-
使用vs code中
João Pinto
编写的Graphviz (dot) language support for Visual Studio Code
插件。这个插件允许你在右侧实时渲染你的图表,十分便利。 -
使用
Gravizo
。这是一个在线渲染图表的网站,允许你通过在Markdown中通过图片插入功能得到在线的即时渲染。使用十分简单,只需正常图片插入操作即可:
![blabla](https://g.gravizo.com/svg? 你的图表) 例子: ![blabla](https://g.gravizo.com/svg? digraph g { splines = "polyline"; k2:s->k1:n [arrowhead=normal;color="green";]; k2:s->Z:n [arrowhead=normal;color="green";]; k1:s->X:n [arrowhead=normal;color="red";]; k1:s->Y:n [arrowhead=normal;color="green";]; k1,k2 [shape=circle;]; Z,Y [shape=triangle;height=1;] X [shape=triangle;height=2;] })
你也可以直接得到图片,只需将你的图表描述进行url编码:
![blabla](https://g.gravizo.com/source/svg?<source_url_url_encoded>)
顺便一提,Gravizo
不仅支持DOT,还支持PlantUML 和 UMLGraph的语法!
但遗憾的是,简书并不支持Gravizo
。
入门操作
-
节点(node)、线(edge)、图(graph)
节点
节点是一个独立的单位,它包含了数据并拥有自己的属性。你可以设置节点的形状、大小和颜色等属性。
你可以给每个节点都设置一个独特的属性:
diagraph example3{ "iamanode" [color="red",shape=circle]; "iamsame" [label="Nodeiam";fontsize=28]; }
属性之间允许使用
,
或;
分隔。另外,最好给节点名加上引号,以防止一些不必要的麻烦。但你也可给所有的节点一个默认的属性,这个默认属性会被节点自身单独设定的属性覆盖:
diagraph example3_1{ node [color="blue"]; }
线
线连接了两个节点。通过属性你可以控制线的外观(大小,粗细等样式),指向等等设置。
diagraph example3_2{ a->b [color="red",style="dotted"]; }
你同样可以给它一个基础的样式:
diagraph example3_3{ edge [style="dotted",arrowhead="normal"]; }
图
图分为有向图(diagraph)和无向图(graph)。
-
有向图
有向图以
diagraph
开始,脚本中的线条用->
表示。在有向图里面,所有的边都默认是存在箭头即有向的(但我们还是可以通过调整边的属性去掉箭头)。前面的例子都是有向图,不再赘述。 -
无向图
无向图以
graph
开始,脚本中的线条用--
表示。在有向图里面,所有的边都默认无向。性质基本和有向图相同。
你在一个文件里只能建立一个的图,或者说一个文件是一个画板,在一个画板上只能容纳一副图表。
但是你可以通过建立子图的方式,来某种意义上变相地容纳多个图,这有点类似于Java中内部类的概念。
diagraph example3_4{ subgraph cluster1{ k1->k2 [color=grey]; } }
注意,子图必须以
cluster
开头命名,否则只是单纯的一个大括号。一个正常的子图是拥有自己的边框的,当边框不存在,很可能你的语法出现了错误。顺便一提,在一张图中,节点名是唯一的。 -
高级操作
在看完前面的例子后,我们应该就能画出一些简单的表格。但是可能有一些人对程序生成的表格并不满意,比如连接节点的线不是直线而是弯曲的曲线,节点的形状不是自己所求,或者追求更细致的图表。
-
节点的
shape
属性我们可以通过
shape
属性将节点设置成不同形状!这里可不只有圆形矩形和三角形。Graphviz提供了许多基于多边形的预设形状,如star,folder,note等等。除此之外你还可以自定义一个多边形,这里简单分享一个自定义多边形的实例:
digraph example4_1 { splines = "polyline"; border = line; subgraph x{ polygon [ shape="polygon"; sides=9; skew=0.0; distortion=0.0; regular=false; peripheries=3; orientation=180; style=rounded ] } }
sides
边数这个属性仅可用于
shape=polygon
的情况,其默认值为4
,呈现为一个矩形。skew
倾斜/偏移这个属性仅可用于
shape=polygon
的情况,其默认值为0.0
。当其为正数时,节点上半部分向右偏移;当为负数时,节点的上半部分向左偏移。distortion
扭曲这个属性仅可用于
shape=polygon
的情况,其默认值为0.0
。当其为正数时,节点上半部分左右扩张;当为负数时,节点的上半部分左右缩小。变形后的上半部分长度计算方式为1 + distortion
。regular
规则度这个属性仅可用于
shape=polygon
的情况,其默认值为false
。当其为true
时,节点形状呈现为正多边形;当为false
时,节点呈现为非正多边形。peripheries
边界条数这个属性对于基于多边形的形状都适用,其默认值为
1
。值得一提是,对于用户自己创建加载的形状,这个属性可能会导致渲染出现错误,这时候应将其设置为0
以取消默认的边界。orientation
旋转这个属性仅可用于
shape=polygon
的情况,其默认值为0.0
。当其为正数时,节点向左旋转;当为负数时,节点向右旋转。旋转的角度为该属性的值。styl=rounded
圆角这个属性适用于所有节点,但是对于本身有圆角的图形可能不会有显现。另外,一个属性只能有一个值。
-
shape=record
基于record的形状与锚点这个形状允许你将一个矩形通过内在的线分为好几部分。语法十分简单:
digraph example4_2 { node01 [shape=record;label="左 | 中 | 右"] }
我们甚至可以更细分:
digraph example4_2_1 { node02 [shape=record;label="左 |{ 中上 |{a | b | c}| 中下 }| 右"] }
提示:每内嵌一次
{}
,分割的方向便会横竖旋转一次。如果我们想要其他节点不只是指向这个节点,而指向这些被分割出的部分,我们可以使用锚点:
digraph example4_2_2 { node01 [shape=record;label="<ybyb>左 | <yb8bo>右"] node01:ybyb -> node01:yb8bo; }
值得一提,锚点的声明一定要写在实际内容前面!
-
节点的
overflow
现象默认来说,节点中的文字不会溢出边界。事实上,节点形状大小会被文字内容给撑大,在这种情况下的
width
和height
属性不会生效。为了让特定的高度和宽度生效,我们必须设置节点的fixedsize
属性。fixedsize
属性有三个值,分别是true
、false
、shape
。-
fixedsize=false
这种情况下,倘若没有给出高度与宽度或者小于包围其文字内容的最小大小,节点形状的大小将按照包围其文字内容的最小大小计算。当给出的高度与宽度大于最小高宽,将按照给出的高宽变形。
-
fixedsize=true
节点形状只与给定的高度与宽度有关,倘若过小,节点的文字内容会超出边界,甚至覆盖到其他节点上去,值得警惕。
-
fixedsize=shape
和
fixedsize=true
情况类似,但是不会覆盖到其他节点,反而会将其他节点推开。不过在高宽过大时,边可能穿过节点边界指向文字内容。
-
-
图的布局
-
rankdir
改变图的排列方向我们可以通过改变图的属性
rankdir
来改变图的排列方向。图默认为rankdir=TB
,即从top到bottom;为了让它能左右排列,我们可以改为rankdir=LR
。 -
rank
改变节点的位置当我们画完一张图的时候,可能会发现图中一些本应该排成一排或一列的节点没有在自己正确的位置。这种时候我们可以通过域和
rank
属性来修正。在rank
中,左上为最小,右下为最大。-
sink
和max
当
rank
被设置为sink
和max
时,节点都会沉到最底部。但是max
比sink
对相邻节点的影响更大。 -
source
和min
当
rank
被设置为source
和min
时,节点都会上升至顶部。source
只允许rank
为source
或min
的位置处于最小阶,而min
则不会排斥其他节点,但实际上两者带来的效果几乎没有差别。 -
same
让所有的节点都处于同一阶。
digraph example4_3 { X->Y->Z; { X,Z; rank=same } }
-
-
-
fill
为节点填色有时候我们想要得到彩色背景的节点,而不仅仅只是通过
color
改变节点边的颜色。通过
style=filled
和fillcolor=red
属性可以改变这一点。digraph example4_4 { k1 [color=blue;style=filled;fillcolor=black;fontcolor=white] }
-
portPos
改变边的指向我们可以让边从一个节点的北部出发,指向一个节点的南部。
digraph example4_5 { k2:s->k1:n [arrowhead=none;color="green"]; } //这里我通过 arrowhead 取消了边的箭头,更多边的属性请查阅官方文档
这里的方向有:
"n","ne","e","se","s","sw","w","nw","c","_"
。e,s,w,n
东南西北,ne,se,sw,nw
同理。这里需要解释的是c
和_
。c
指的是从节点的中心指出或者指入。_
则是让程序自己寻找一个可能的值,在空间允许的情况下和c
同效果。 -
边的
style
属性solid
默认的实线,dashed
虚线,dotted
点线,bold
粗线,tapered
锥形线,invis
不可见。 -
在
lable
中使用HTML标签lable
属性值现在支持HTML标签,你可以用HTML标签对文字的样式进行修改(包括大小,颜色,字体,对齐甚至渐变)。详情请见官方文档。 -
splines
改变线的形状-
true/spline
这是默认属性。这将使得边为样条线,即可曲可直,可能为了指向终点穿过节点。
-
false/line
当被设置为
false
或line
时,边只为直线段,也可能为了指向终点穿过节点,“直来直去”。 -
polyline
折线,保证所有边都为直线,边会通过折来转向,但转向角度不一定时90度。
-
ortho
折线,保证所有边都为直线,转向角度为90度,可能为了指向终点穿过节点。
-
curved
曲线,保证所有边都为曲线,可能为了指向终点穿过节点。
-
none
/“”
不显示边。
-
如何查阅资料
- 官网
- 博客/QA平台
- 参考资料
- graphviz官网
- stackflow-polylinesedges when using ports graphviz
- Graphviz 画图教程 by EdisonLeejt
- 绘图工具graphviz学习使用 by hustlijian
- Graphviz 画图的一些总结 by 小胖西瓜
- Graphviz绘图 - DOT语言 by 老彭
- 使用DOT语言和Graphviz绘图(翻译) by Tony Ballantyne 和 zxyblog
感谢他们的思考与无私分享。
网友评论