| 导语 一直以来自己都是通过Visio在画流程图和架构图,原来通过写代码的方式也可以画图,这种方式简洁而高效,完美搭配vim,并且可以轻松实现脚本化,于是就入坑了。
教你用代码画一颗树
写在前面
优点 自动布局和连线 易于实现脚本化
缺点 无法绘制需要自定义或固定布局的图 下面我们就来画一棵Merkle树吧
代码的分割线
教你用代码画一颗树
等等,Merkle树是神马?
Merkle树,也叫哈希树,是一种用做快速归纳和校验大规模数据完整性的树形数据结构。
下图就是《精通比特币》一书中的Merkle树示意图,图中每个叶子节点即一笔交易,两两组合,逐层Hash到根节点。通过Merkle树可以在只知道部分节点的Hash的情况下,就能验证某笔交易是否存在或正确,而无需获取所有交易节点的Hash值。要知道一般这个代价是很大的,以比特币区块为例,目前整个区块链账本大小接近200G。
所以,Merkle树也是SPV(简单的支付认证,即Simple Payment Verification)的基础。 🔻
教你用代码画一颗树
Merkle树应用
快速比较大量数据:当两个Merkle树的根哈希值相同时,说明所代表的的数据都相同 快速定位修改:如上图,如果交易K发生改变,那么就会导致HK、HKL、HIJKL、HIJKLMNOP和Merkle Root发生改变。所以,我们想要快速定位,只需要沿着Root => HIJKLMNOP => HIJKL => HKL => HK,就可以定位到交易K发生改变 零知识证明:例如,想要证明一组交易中包含某个交易K,但又不想让对方知道交易K的具体内容,那么就可以构建Merkle树,向对方公布HK、HL、HKL、HIJKL、HIJKLMNOP和Merkle Root,对方就可以确认交易K的存在,但无法知道交易K的具体内容。
开始画图/写代码 🔻 怎样画节点? 最简单的节点
寥寥四行代码就画出了3个节点
- <font color="rgb(102, 217, 239)">digraph</font> G1 { <font color="rgb(102, 217, 239)">A</font> B C }
复制代码
教你用代码画一颗树
装饰节点
- <div class="quote"><blockquote><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">digraph G2 {
- //对节点进行全局设置
- node [fontname=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"Microsoft YaHei"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fontsize=15 shape=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"record"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> color=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"black"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fillcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"gray90"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">style=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"filled,bold"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">];
- HA [label=<H<SUB>A</SUB>>]
- HK [label=<H<SUB>K</SUB>> fillcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"forestgreen"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fontcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"white"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">]
- HKL [label=<H<SUB>KL</SUB>> color=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"dodgerblue3"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> style=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"filled,bold,dashed"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">]
- }</span>
复制代码
教你用代码画一颗树
节点属性
[td]属性名 | 默认值 | 说明 | label | node name | 节点显示内容 | color | black | node边框颜色 | fontcolor | black | 字体颜色 | fillcolor |
| 背景色 | fontname | Times-Roman | 字体 | fontsize | 14 | 字体大小 | shape | ellipse | 形状:box、ellipse、circle、diamond、
plaintext、point、triangle、invtriangle | style |
| 图形样式: bold、dashed、dotted、filled | image |
| 背景图片地址 |
怎样画连线?最简单的连线 通过->很形象的建立了节点间的有向连线
- <font size="4"><span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(166, 226, 46);">digraph</span> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">G3</span> { <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">A</span>
- <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">B</span>
- <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span>
- <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">A</span> -> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span>
- <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">B</span> -> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span> }</font>
复制代码
教你用代码画一颗树
装饰连线
- <font size="4">digraph G4 {
- //边全局设置
- edge [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold"</span>];
- A
- B
- C
- A -> C [label=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"A2C"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"green"</span> arrowhead=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"diamond"</span>]
- B -> C [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold,dashed"</span> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> arrowsize=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"2.0"</span>]
- }</font>
复制代码
教你用代码画一颗树教你用代码画一颗树
连线属性
[td]属性名 | 默认值 | 说明 | label |
| 描述关系 | color | black | 箭头颜色 | fontcolor | black | 关系文字颜色 | dir | forward | 设置方向:forward、back、both、none | arrowhead | normal | 箭头头部形状:box、crow、diamond、dot、none、normal、vee | arrowtail | none | 箭头尾部形状 | arrowsize | 1.0 | 箭头大小 | style |
| 图形样式: bold、dashed、dotted、filled | 仿制Merkle树完整代码- <font size="4">$ cat MerkleTree.dot
- digraph MerkleTree {
- rankdir = BT;
- label=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"MerkleTree draw by jasonruan"</span>
- node [fontname=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"Microsoft YaHei"</span> fontsize=15 shape=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"record"</span> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"black"</span> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"gray90"</span>style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold"</span>];
- edge [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold"</span>];
- HA [label=<H<SUB>A</SUB>>]
- HB [label=<H<SUB>B</SUB>>]
- HAB [label=<H<SUB>AB</SUB>>]
- HC [label=<H<SUB>C</SUB>>]
- HD [label=<H<SUB>D</SUB>>]
- HCD [label=<H<SUB>CD</SUB>>]
- HABCD [label=<H<SUB>ABCD</SUB>>]
- HE [label=<H<SUB>E</SUB>>]
- HF [label=<H<SUB>F</SUB>>]
- HEF [label=<H<SUB>EF</SUB>>]
- HG [label=<H<SUB>G</SUB>>]
- HH [label=<H<SUB>H</SUB>>]
- HGH [label=<H<SUB>GH</SUB>>]
- HEFGH [label=<H<SUB>EFGH</SUB>>]
- HABCDEFGH [label=<H<SUB>ABCDEFGH</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold"</span>]
- HI [label=<H<SUB>I</SUB>>]
- HJ [label=<H<SUB>J</SUB>>]
- HIJ [label=<H<SUB>IJ</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
- HK [label=<H<SUB>K</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"forestgreen"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
- HL [label=<H<SUB>L</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
- HKL [label=<H<SUB>KL</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
- HIJKL [label=<H<SUB>IJKL</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
- HM [label=<H<SUB>M</SUB>>]
- HN [label=<H<SUB>N</SUB>>]
- HMN [label=<H<SUB>MN</SUB>>]
- HO [label=<H<SUB>O</SUB>>]
- HP [label=<H<SUB>P</SUB>>]
- HOP [label=<H<SUB>OP</SUB>>]
- HMNOP [label=<H<SUB>MNOP</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
- HIJKLMNOP [label=<H<SUB>IJKLMNOP</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
- {HA,HB} -> HAB
- {HC,HD} -> HCD
- {HAB,HCD} -> HABCD
- {HE,HF} -> HEF
- {HG,HH} -> HGH
- {HEF,HGH} -> HEFGH
- {HABCD,HEFGH} -> HABCDEFGH
- {HI,HJ} -> HIJ
- {HK,HL} -> HKL
- {HIJ,HKL} -> HIJKL
- {HM,HN} -> HMN
- {HO,HP} -> HOP
- {HMN,HOP} -> HMNOP
- {HIJKL,HMNOP} -> HIJKLMNOP
- HABCDEFGHIJKLMNOP [label=<Root<br/><SUB>ABCDEFGHIJKLMNOP</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
- {HABCDEFGH,HIJKLMNOP} -> HABCDEFGHIJKLMNOP</font>
复制代码
Merkle树仿制图
教你用代码画一颗树
工具安装最后再来介绍下画图工具和vim插件安装。 软件安装官网:https://graphviz. gitlab .io/ 当前版本:graphviz-2.40.1.tar.gz 这里采用源码方式安装: - <font size="4">$ wget https://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz
- $ tar -zxf graphviz.tar.gz
- $ <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">cd</span> graphviz-2.40.1
- $ ./configure --prefix=/home/rzexin/Software/ALL
- $ make -j2 && make install</font>
复制代码
vim整合(1)插件安装 .vimrc新增
- <font size="4">Plugin <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">'wannesm/wmgraphviz.vim'</span></font>
复制代码
执行安装命令
- <font size="4">:PluginInstall</font>
复制代码
(2)vim配置 - <font size="4"><span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(249, 38, 114);">function</span> HeaderDot()
- call append (1,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"digraph G {"</span>)
- call append (2,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">""</span>)
- call append (3,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"}"</span>)
- normal 3G
- endfunction
- autocmd bufnewfile *.dot call HeaderDot()
- nmap <Leader>ln :w<CR>:! dot -Tpng -o %<.png %<CR>:! eog %<.png <CR>
- nmap <Leader>ls :w<CR>:! dot -Tsvg -o %<.svg %<CR>:! eog %<.svg <CR></font>
复制代码
配置说明: 打开.dot后缀文件,自动执行HeaderDot函数创建dot文件框架
vim normal模式下执行,ln将自动保存png格式文件并自动预览,同样,使用,ls将保存为svg格式文件并自动预览
%<表示去掉后缀的当前文件名
写在最后
graphviz的功能也确实强大,自己只是初步入门,但感觉这点入门知识也已经大大提升了自己的工作效率。之前通过Visio画图要不断的去调整样式、配色,是件很繁琐的事情,特别是当要修改时,可能要不断调整已有图形的布局,很是费时。现在,通过graphviz一切都自动的帮你完成好了,而且图形还挺美观。自己能不入坑吗:) end
|