0%

TikZ入门教程

By Z.H. Fu
https://fuzihaofzh.github.io/blog/

引言

在绘制流程框图时,有许多工具可以采用,最著名的有微软的Viso,而开源的有Graphviz、PGF/TikZ,最近要再Mac上画一个流程图,Graphviz是采用dot语言的一个矢量图生成系统,但是不支持LaTeXLaTeX公式,安装也比较麻烦。PGF是用于生成矢量图的一种语言,而TikZ则是在Tex环境下的一个宏包,实现了对PGF的封装,所以我们要使用TikZ,就需要先配置LaTeXLaTeX环境,用TikZ绘制出来的图形效果非常好,原生支持所有LaTeXLaTeX语法,同时能和正文的文字字体保持高度一致,但是学习曲线略微陡峭,适合有排版强迫症的同学。那么下面我们一步一步地熟悉用TikZ来绘制流程图。

![TikZ_sample](/blog/images/tikz/TikZ_sample.svg)

环境安装与配置

我们首先要安装Tex环境,Windows系统推荐Texlive 完整安装,Mac系统推荐MacTex 完整安装后,在Windows下,已安装默认编辑器WinEdt,而在Mac下的编辑器则是TeXShop,这两个编辑器都非常好用,直接用就可以了。

第一个例子

我们先从一个最简单的例子开始:画一条直线。
  代码如下:

1
2
3
4
5
6
7
\documentclass[tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (1,1);
\end{tikzpicture}
\end{document}

这样,我们得到了一个pdf文件,我们用pdf2svg工具将其转换为svg格式的矢量图。
输出:

![TikZ_s0](/blog/images/tikz/TikZ_s0.svg)

带\的都是LaTeX的宏命令,可以看到,这段代码的核心就一句话 \draw (0,0) -- (1,1); 这句话的意思就是从(0,0)到(1,1)画一条线段。我们还可以画的稍微复杂一点:

1
2
3
4
5
6
7
8
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw [color=blue!50,->](0,0) node[left]{$A$}-- node [color=red!70,pos=0.25,above,sloped]{Hello}(3,3) node[right]{$B$};
\end{tikzpicture}
\end{document}

输出:

![TikZ_s1](/blog/images/tikz/TikZ_s1.svg)
  可以看到,`\draw`后面的方括号中跟的是对线的一些设置,`color=blue!50`表示的是用50%的蓝色,因为LaTeX中,%用作了注释,所以这里用!替代,`->`表示的是线形是一个箭头,我们注意到,在起点坐标,--,终点坐标后面,我们分别加入了一个node元素,起点后面的node表示的是加入一个标示,它在坐标点(0,0)的左边,`--`后面的node采用70%的红色,位置在线段的上方0.25的位置,随线段倾斜,花括号中是node的文字,为Hello,终点坐标同理。node经常用于加入一些标注,这一点我们在后面将会看到。

一些复杂的形状

在TikZ中,除了画线段之外,还支持各种复杂的形状,下面一个例子给出了一些常见的形状:

1
2
3
4
5
6
7
8
9
10
11
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) circle (10pt); %画一个圆心在原点,半径为10pt的圆;
\draw (0,0) .. controls (1,1) and (2,1) .. (2,0); %画一个起点为(0,0),终点为(2,0),控制点为(1,1),(2,1)的贝塞尔曲线;
\draw (0,0) ellipse (20pt and 10pt); %画一个中心在原点,长轴、短轴分别为20pt和10pt的椭圆;
\draw (0,0) rectangle (0.5,0.5); %画一个从(0,0)到(0.5,0.5)的矩形
\filldraw[fill=green!20!white, draw=green!50!black](0,0) -- (3mm,0mm) arc (0:30:3mm) -- cycle;画一个扇形,并填充,扇形的边色和填充色的透明度不同。
\end{tikzpicture}
\end{document}

输出:

![TikZ_s2](/blog/images/tikz/TikZ_s2.svg)
## 属性预定义   在刚才的例子中我们看到,随着我们对样式需求的多样化,属性越来越长,而且多个实体之间往往具有相同的属性,这样一来,我们希望能预定义一个属性集合,到时候直接赋给相应的实体,TikZ本身就是个宏,因此它为我们提供了强大的属性定义功能,来看这段代码:
1
2
3
4
5
6
7
8
9
10
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
[L1Node/.style={circle, draw=blue!50, fill=blue!20, very thick, minimum size=10mm},
L2Node/.style={rectangle,draw=green!50,fill=green!20,very thick, minimum size=10mm}]
\node[L1Node] (n1) at (0, 0){$\int x dx$};
\node[L2Node] (n2) at (2, 0){$n!$};
\end{tikzpicture}
\end{document}
输出:
![TikZ_s3](/blog/images/tikz/TikZ_s3.svg)
在这段代码中,我们在最开始定义了两个名为L1Node和L2Node的属性,在生成node结点的时候直接填到属性的位置即可。

循环

TikZ相比于Viso的一个优势就在于其循环功能,Viso里面要循环画十个圆就得复制十次,还要调节各自的位置,如果遇到需要调整位置又得重来,TikZ这种命令行的方式能直接画出来,如果需要调整位置,更改参数即可,我们在上一个例子上生成十个结点:

1
2
3
4
5
6
7
8
9
10
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
[L1Node/.style={circle, draw=blue!50, fill=blue!20, very thick, minimum size=10mm},
L2Node/.style={rectangle,draw=green!50,fill=green!20,very thick, minimum size=10mm}]
\foreach \x in {1,...,5}
\node[L1Node] (w1_\x) at (2*\x, 0){$\int_\Omega x_\x$};
\end{tikzpicture}
\end{document}

输出:

![TikZ_s4](/blog/images/tikz/TikZ_s4.svg)
## node树 node结点不但可以用于添加标识,还可以来绘制树形图,下面看一个例子
1
2
3
4
5
6
7
8
9
10
11
12
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\node {root}
child {node {a1}}
child {node {a2}
child {node {b1}}
child {node {b2}}}
child {node {a3}};
\end{tikzpicture}
\end{document}
输出:
![TikZ_s5](/blog/images/tikz/TikZ_s5.svg)
稍微加点样式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
\documentclass[tikz,convert=pdf2svg]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
[every node/.style={fill=blue!30,draw=blue!70,rounded corners},
edge from parent/.style={blue,thick,draw}]
\node {root}
child {node {a1}}
child {node {a2}
child {node {b1}}
child {node {b2}}}
child {node {a3}};
\end{tikzpicture}
\end{document}
输出:
![TikZ_s6](/blog/images/tikz/TikZ_s6.svg)
## 绘制函数图像 TikZ提供了强大的函数绘制功能,下面的代码展示了如何绘制函数,当然,绘制数据图表并非TikZ擅长的事情,也并非其设计初衷,TikZ着眼于定性的图表,定量数据的演示还是用其他工具绘制较好。
1
2
3
4
5
6
7
8
9
10
11
12
13
\documentclass[tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[domain=0:4]
\draw[very thin,color=gray] (-0.1,-1.1) grid (3.9,3.9);
\draw[->] (-0.2,0) -- (4.2,0) node[right] {$x$};
\draw[->] (0,-1.2) -- (0,4.2) node[above] {$f(x)$};
\draw[color=red] plot (\x,\x) node[right] {$f(x) =x$};
% \x r 表示弧度
\draw[color=blue] plot (\x,{sin(\x r)}) node[right] {$f(x) = \sin x$};
\draw[color=orange] plot (\x,{0.05*exp(\x)}) node[right] {$f(x) = \frac{1}{20} \mathrm e^x$};
\end{tikzpicture}
\end{document}
输出:
![TikZ_s7](/blog/images/tikz/TikZ_s7.svg)
## 图 TikZ提供了图的支持,通过类似于dot语言的方式来生成图关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs}
\begin{document}
\begin{tikzpicture}
\graph {
"$x_1$" -> "$x_2$"[red] -> "$x_3,x_4$";
"$x_1$" ->[bend left] "$x_3,x_4$";
};
\end{tikzpicture}
\begin{tikzpicture}
\graph {
a -> {
b -> c,
d -> e
} -> f
};
\end{tikzpicture}
\end{document}
输出:
![TikZ_s8](/blog/images/tikz/TikZ_s8.svg)
![TikZ_s82](/blog/images/tikz/TikZ_s82.svg)
## 总结 关于TikZ的入门就写到这里,通过上面几个例子我们可以看出,TikZ能精确绘制各种复杂的示意图,能非常好地完成Viso,Graphviz等工具完成的功能。参考文献中给出了一个例子的网站,通常想绘制的图形都能在这上面搜到,自己稍微改一改就能直接使用。 ## 参考文献 [1] http://www.texample.net/tikz/examples/ (提供了大量示例) [2] The TikZ and PGF Packages Manual(TikZ的手册) [3] A very minimal introduction to TikZ (一个入门教程)