Create diagrams using code with Graphviz

栏目: IT技术 · 发布时间: 4年前

内容简介:Have you ever had to draw an architecture diagram and found the repetitive clicking and dragging tedious? Did you have to do modifications to that diagram and found it complicated?Before we start writing graphs, we need to learn how we can convert our code

Have you ever had to draw an architecture diagram and found the repetitive clicking and dragging tedious? Did you have to do modifications to that diagram and found it complicated?

Graphviz is an open source graph visualization software that allows us to decribe a diagram using code, and have it automatically drawn for us. If the diagram needs to be modified in the future, we just need to modify the description and the nodes and edges will be repositioned automatically for us.

Drawing graphs

Before we start writing graphs, we need to learn how we can convert our code into an image so we can test what we are doing.

Webgraphviz.com can be used to draw graphs from a browser.

We can also install the command line tool in Ubuntu using apt:

sudo apt install graphviz

This will install, among other things, the dot CLI, which can be used to generate images from text files:

dot -Tpng input.gv -o output.png

In the example above we are specifying png as the output ( -Tpng ), but there are many options available . As we can see, the input files commonly use the gv extension.

DOT

DOT is the most common format used to describe graphs to be parsed by Graphviz.

Basics

A simple graph has this form:

graph MyGraph {
  begin -- end
}

Create diagrams using code with Graphviz

If we want to use a directed graph (one with arrows), we need to use digraph instead:

digraph MyGraph {
  begin -> end
}

Create diagrams using code with Graphviz

Arrows can be in one direction or bidirectional:

digraph MyGraph {
  a -> b
  a -> c [dir=both]
}

Create diagrams using code with Graphviz

Shapes

If we don’t like ovals, we can use other shapes:

digraph MyGraph {
  a [shape=box]
  b [shape=polygon,sides=6]
  c [shape=triangle]
  d [shape=invtriangle]
  e [shape=polygon,sides=4,skew=.5]
  f [shape=polygon,sides=4,distortion=.5]
  g [shape=diamond]
  h [shape=Mdiamond]
  i [shape=Msquare]
  a -> b
  a -> c
  a -> d
  a -> e
  a -> f
  a -> g
  a -> h
  a -> i
}

Create diagrams using code with Graphviz

The different supported shapes can be found in the node shapes section of their documentation .

We can also add some color and style to our nodes:

digraph MyGraph {
  a [style=filled,color=green]
  b [peripheries=4,color=blue]
  c [fontcolor=crimson]
  d [style=filled,fillcolor=dodgerblue,color=coral4,penwidth=3]
  e [style=dotted]
  f [style=dashed]
  g [style=diagonals]
  h [style=filled,color="#333399"]
  i [style=filled,color="#ff000055"]
  j [shape=box,style=striped,fillcolor="red:green:blue"]
  k [style=wedged,fillcolor="green:white:red"]
  a -> b
  a -> c
  a -> d
  a -> e
  b -> f
  b -> g
  b -> h
  b -> i
  d -> j
  j -> k
}

Create diagrams using code with Graphviz

The different color names can be found in the color names documentation .

Arrows

Arrows’ tails and heads can also be modified:

digraph MyGraph {
  a -> b [dir=both,arrowhead=open,arrowtail=inv]
  a -> c [dir=both,arrowhead=dot,arrowtail=invdot]
  a -> d [dir=both,arrowhead=odot,arrowtail=invodot]
  a -> e [dir=both,arrowhead=tee,arrowtail=empty]
  a -> f [dir=both,arrowhead=halfopen,arrowtail=crow]
  a -> g [dir=both,arrowhead=diamond,arrowtail=box]
}

Create diagrams using code with Graphviz

The different arrow types can be found in the arrow shapes documentation .

As well as adding styles to the arrow line:

digraph MyGraph {
  a -> b [color="black:red:blue"]
  a -> c [color="black:red;0.5:blue"]
  a -> d [dir=none,color="green:red:blue"]
  a -> e [dir=none,color="green:red;.3:blue"]
  a -> f [dir=none,color="orange"]
  d -> g [arrowsize=2.5]
  d -> h [style=dashed]
  d -> i [style=dotted]
  d -> j [penwidth=5]
}

Create diagrams using code with Graphviz

If we pay attention to the code and diagram above, we can see that when we specify multiple colors for an arrow, there will be one line for each color, if we don’t specify any weight. If we want a single arrow with multiple colors, at least one color has to specify the weight percentage of the line to cover:

a -> e [dir=none,color="green:red;.3:blue"]

Labels

We can add labels to nodes:

digraph MyGraph {
  begin [label="This is the beginning"]
  end [label="It ends here"]
  begin -> end
}

Create diagrams using code with Graphviz

As well as vertices:

digraph MyGraph {
  begin
  end
  begin -> end [label="Beginning to end"]
}

Create diagrams using code with Graphviz

We can style our labels:

digraph MyGraph {
  begin [label="This is the beginning",fontcolor=green,fontsize=10]
  end [label="It ends here",fontcolor=red,fontsize=10]
  begin -> end [label="Beginning to end",fontcolor=gray,fontsize=16]
}

Create diagrams using code with Graphviz

Clusters

Clusters are also called subgraphs. The name of a cluster needs to be start with cluster_ , or it won’t be contained in a box.

digraph MyGraph {
  subgraph cluster_a {
    b
    c -> d
  }
  a -> b
  d -> e
}

Create diagrams using code with Graphviz

Clusters can be nested as neccessary:

digraph MyGraph {
  subgraph cluster_a {
    subgraph cluster_b {
      subgraph cluster_c {
        d
      }
      c -> d
    }
    b -> c
  }
  a -> b
  d -> e
}

Create diagrams using code with Graphviz

HTML

HTML allows us to create more complicated nodes that can be split into sections. Each section can be referred to in the graph independently:

digraph MyGraph {
    a [shape=plaintext,label=<
      <table>
        <tr>
          <td>Hello</td>
          <td>world!</td>
        </tr>
        <tr>
          <td colspan="2" port="a1">are you ok?</td>
        </tr>
      </table>
    >]
    b [shape=plaintext,label=<
      <table border="0" cellborder="1" cellspacing="0">
        <tr>
          <td rowspan="3">left</td>
          <td>top</td>
          <td rowspan="3" port="b2">right</td>
        </tr>
        <tr>
          <td port="b1">center</td>
        </tr>
        <tr>
          <td>bottom</td>
        </tr>
      </table>
    >]

    a:a1 -> b:b1
    a:a1 -> b:b2
}

Create diagrams using code with Graphviz

Only a subset of HTML can be used to create nodes, and the rules are pretty strict. In order for the node to display correctly, we need to set the shape to plaintext .

Another important thing to notice is the port attribute, which allows us to reference that specific cell by using a colon ( a:a1 ).

We can style our HTML nodes, but we can only use a subset of HTML:

digraph MyGraph {
    a [shape=plaintext,label=<
      <table>
        <tr>
          <td color="#ff0000" bgcolor="#008822"><font color="#55ff00">Hello</font></td>
          <td>world!</td>
        </tr>
        <tr>
          <td colspan="2" color="#00ff00" bgcolor="#ff0000">
            <font color="#ffffff">are you ok?</font>
          </td>
        </tr>
      </table>
    >]
}

Create diagrams using code with Graphviz

Images

Sometimes we want to use specify icons for our nodes, this can be done with the image attribute:

digraph MyGraph {
  ec2 [shape=none,label="",image="icons/ec2.png"]
  igw [shape=none,label="",image="icons/igw.png"]
  rds [shape=none,label="",image="icons/rds.png"]
  vpc [shape=none,label="",image="icons/vpc.png"]

  subgraph cluster_vpc {
    label="VPC"

    subgraph cluster_public_subnet {
      label="Public Subnet"
      ec2
    }

    subgraph cluster_private_subnet {
      label="Private Subnet"
      ec2 -> rds
    }

    vpc
    igw -> ec2
  }

  users -> igw
}

Create diagrams using code with Graphviz

Ranks

Ranks are one of the most complicated things to understand, since they alter how the rendering engine works. Here I’m just going to cover some of the basic things that I find useful.

A Graph will normally be rendered top to bottom:

digraph MyGraph {
  a -> b
  b -> c
  a -> d
  a -> c
}

Create diagrams using code with Graphviz

Using the rankdir attribute, we can render it left to right:

digraph MyGraph {
  rankdir=LR

  a -> b
  b -> c
  a -> d
  a -> c
}

Create diagrams using code with Graphviz

Ranking can also be used to force a node to be at the same level as another node:

digraph MyGraph {
  rankdir=LR

  a -> b
  b -> c
  a -> d
  a -> c

  {rank=same;c;b}
}

Create diagrams using code with Graphviz

In the example above we use rank=same to align node c with node b .

The rankdir attribute is global, so it can’t be changed inside a cluster, but using rank we can simulate an LR direction inside clusters:

digraph MyGraph {
  subgraph cluster_A {
    a1 -> a2
    a2 -> a3

    {rank=same;a1;a2;a3}
  }

  subgraph cluster_B {
    a3 -> b1
    b1 -> b2
    b2 -> b3

    {rank=same;b1;b2;b3}
  }

  begin -> a1
}

Create diagrams using code with Graphviz

We can combine rank with constraint=false to create more compact graphs:

digraph MyGraph {
  subgraph cluster_A {
    a1
    a2
    a3
    {rank=same;a1;a2;a3}
  }

  subgraph cluster_B {
    b1
    b2
    b3

    {rank=same;b1;b2;b3}
  }

  begin -> a1
  a1 -> a2 [constraint=false]
  a2 -> a3 [constraint=false]
  a3 -> b1
  b1 -> b2
  b2 -> b3
}

Create diagrams using code with Graphviz

Rank can also be used to specify the distance between each node:

digraph MyGraph {
  rankdir=LR
  ranksep=1
  a -> b
  b -> c
  c -> d
}

Create diagrams using code with Graphviz

The default value for ranksep is .5 .

Conclusion

In this post we learned how we can use Graphviz to generate graphs based on a declarative language. This has made it a lot easier for me to draw architecture diagrams and modify them in the future.

I presented the features that I consider most important for everyday use, but there are a good amount of features that I didn’t cover and frankly, I don’t understand.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

思想的未来

思想的未来

(美)劳伦斯﹒莱斯格 / 李旭 / 中信出版社 / 2004-10 / 29.00元

因特网革命已到来,一些人说它已经过去,革命缘何而来?又缘何而去呢? 劳伦斯·莱斯格对因特网革命中为何会出现一种反革命的破坏性力量及后果做出了解释。创作之所以繁荣,是因为因特网保护了创新的公共资源。是因为因特网保护了创新的公共资源。因特网的独特设计营造出一个中立的平台。最广大范围的作者们可在此平台上进行试验。围绕此平台的法律架构对这一自由空间给予了保护,以使文化和信息——我们这个时代的......一起来看看 《思想的未来》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码