用 TikZ 绘制技术图形

用 TikZ 绘制技术图形 每当我制作技术文档演示文稿、出版物、技术演讲…时制作其中的图形曾经是我最头疼的事情。你知道我在说什么吗我会试图将箭头对齐到框的边缘或者稍微居中一个标签或者因为我不太会用鼠标而消除这些小瑕疵。无论我多么努力想让它完美总是差那么一点点刚好能看出来。这一切在我发现矢量图形以及如何轻松地用数学术语指定技术图示后改变了。我邀请你走我走过的路停止在draw.io、Visio或Inkscape中绘制图表。编写描述你图表的代码。1、使用图形语言的好处像大多数文章一样我喜欢从提供一些动机开始。为什么有人会费劲地为他们的图形编写代码为什么要在一个本质上是视觉的东西上浪费时间写抽象描述我能想到很多原因图表变成纯文本因此可以通过代码自动化并通过版本控制软件跟踪。你需要经常绘制的重复部分可以抽象成函数甚至可以参数化。无限分辨率和控制可以精确对齐图表的各个部分。更容易回收和调整旧图形。如果你遵循我的方法LaTeX数学集成在你的图形中与文档其余部分的质量相匹配。如果你已经在使用某种编程环境来制作文档参见我在下面文章中的想法你不必切换到不同的程序来制作图形。那么我最终选择的语言是什么它叫TikZ是LaTeX生态系统的一部分。2、我使用的语言TikZTikZ是一个名为PGF便携式图形格式的高级前端两者都由Beamer的作者、无与伦比的Till Tantau创建。PGF/TikZ作为LaTeX包在CTAN上分发并有一个令人难以置信的手册前100页左右就能让你上手通过非常实用的教程但后面还有1300页关于PGF和TikZ所有功能的详细说明。如上所述作为LaTeX的一部分意味着TikZ图形与我在LaTeX中制作的任何文档都非常紧密地集成在一起。图形中的任何标签都与主文档的字体相匹配数学符号也具有相同的质量。话虽如此你总是可以使用TikZ和LaTeX引擎来制作不嵌入任何文档的图形参见standalone文档类并将其包含在你正在处理的任何其他类型的文档中。TikZ的另一个优势是它有许多很棒的支持库提供了现成的图形供重用。一些特别值得注意的例子tikz-uml用于UML图表circuitikz用于绘制电路图包括逻辑门和晶体管PGFPlots用于创建方程或来自外部文件的原始数据的2D和3D图内置的思维导图库你可能想知道是否还有其他选择。确实有。我知道至少还有两个你可以用PostScript语言编写图形LaTeX有PSTricks包来帮助实现。你可以使用Asymptote这是一种独立的语言感觉很像C/C比PGF/TikZ性能更好对3D图形有更好的支持。还有一个LaTeX包用于在文档中嵌入Asymptote图形。我自己从Asymptote开始但后来切换到了TikZ因为它更容易使用而且有现成的库为我节省了很多时间。在这个意义上我用性能换取了便利。如果你仍然持怀疑态度我邀请你看看这个示例画廊体验一下TikZ的所有功能。3、TikZ的基本概念TikZ基本上是一支笔你可以通过数学操作引导它在画布上移动。在过程中你可以告诉笔改变颜色、粗细、线条样式甚至从画布上的一个点跳到另一个点而不绘制它们之间的路径。到目前为止这与一般的图形语言概念没有太大不同。TikZ的优势在于它的简洁性和它提供的高级结构使创建图表更容易。从一个非常基础的例子可以看出这一点绘制矩形。假设我们想画一个宽度为5个单位、高度为2个单位的矩形。有很多种方法可以做到。让我们来探索它们。本文中的所有代码示例都假设你在导言区有\usepackage{tikz}并将代码嵌入到tikzpicture环境中。% 直接指定坐标 \draw (0, 0) -- (5, 0) -- (5, 2) -- (0, 2) -- (0, 0); % 稍微好一点通过将最后一个点连接到第一个点来闭合路径 \draw (0, 0) -- (5, 0) -- (5, 2) -- (0, 2) -- cycle; % 指定相对坐标(5, 0) 表示在当前点右侧5个单位 \draw (0, 0) -- (5, 0) -- (0, 2) -- (-5, 0) -- cycle; % 如果使用单个它计算相对坐标但不使新点成为当前点 % 所以所有坐标都是相对于我们指定的第一个点计算的 \draw (0, 0) -- (5, 0) -- (5, 2) -- (0, 2) -- cycle; % 在许多场景中另一个方便的方法是通过水平和垂直线连接两个点 \draw (0, 0) -| (5, 2) -| (0, 0); % 当然对于像矩形这样的基本形状已经有更方便的方式 \draw (0, 0) rectangle (5, 2);简单的5x2矩形我应该更多地解释倒数第二个例子。你看到命令也告诉TikZ在绘制时如何在两点之间移动。两个破折号只是表示沿直线移动。但当我们使用像(0, 0) -| (5, 2)这样的形式时我们表示从(0, 0)水平向外移动直到在(5, 2)正下方然后垂直移动到(5, 2)。还有一个等效的|-指令。它在上面的例子中同样有效尽管线段会以不同的顺序绘制。样式呢非常简单只需提供适当的选项\draw [red, fillblue] (0, 0) rectangle (5, 2);带样式的矩形#### 节点除了在点之间绘制路径你还可以在给定点创建节点。节点是图片的一个元素它有与之关联的形状、可选的文本标签和若干锚点。这相当抽象。让我具体一点。我认为节点的原始目的是说明树形图中的节点或流程图中的步骤。我之所以这么认为是因为默认节点形状是矩形。以下是当我要求TikZ绘制默认节点形状时发生的情况\node [draw] (my node) at (0, 0) {This is my node};带标签的节点作者截图注意语法的几个要点你可以提供可选的节点名称我在上面使用了my node以便在后面的代码中引用该节点。你还可以提供它的位置这是可选的默认为当前点。花括号之间的文本是节点标签。这是强制性的。你可以通过空的一对花括号来拥有空标签。那么什么是节点锚点注意节点不是单个点。当我为节点指定位置时节点的锚点就是被放置在那里的位置。默认情况下这是节点的中心但我可以更改它\node [circ] at (0, 0) {}; % 标记 (0, 0) \node [circ] at (2, 0) {}; % 标记 (2, 0) \node [draw] at (0, 0) {A}; % 锚定在中心 \node [draw, anchorsouth west] at (2, 0) {B}; % 锚定在左下角锚定节点作者截图节点也有形状。你可以为节点指定不同的形状\node [draw,circle] at (0, 0) {AA}; \node [draw, anchorsouth west,ellipse] at (2, 0) {BB};节点形状可以更改有很多库定义了许多相当复杂的节点形状。例如circuitikz库将所有电路元件定义为节点形状。你也可以定义自己的节点形状及其自定义锚点。需要注意的是你必须用PGF来做这件事它比TikZ低级得多所以语法没有那么友好。节点如果不能连接就没多大用处。这里有一些不同的连接方式\node [draw,regular polygon, regular polygon sides3] (A) at (0, 0) {A}; \node [draw, anchorsouth west, regular polygon, regular polygon sides5] (B) at (2, 0) {B}; \draw (A.east) -- (B.west) (A.north) to [out90, in90] (B.north);不同的节点连接方式注意第二种方式给了你更多的灵活性你指定线条从源点在这种情况下是A的北锚点出来的角度以及它进入目标B的北锚点的角度。TikZ自动为你绘制曲线路径。还有一个有用的命令允许你定义命名坐标并在后面按名称引用它们\coordinate (A) at (0, 0); \coordinate (B) at (1, 2.5); \coordinate (C) at (2, -3); \draw (A) -- (B) -- (C) -- cycle; \node [circ] at (A) {A}; \node [circ] at (B) {B}; \node [circ] at (C) {C};定义命名坐标最后为了将这些概念结合在一起注意你可以在绘制路径时定义节点和坐标\draw (0,0) coordinate (A) -- (1, 2) coordinate (B) -- node [draw, right] (C) {C} (0, -2); \draw [-] (C.north) to [out30, in60] (B);在绘制路径时定义节点和坐标## 4、更高级的概念当然一篇文章不可能涵盖TikZ的所有功能请参阅手册但我想介绍几个我经常利用的有用概念。坐标计算编写绘图程序当然涉及计算大量坐标。TikZ通过允许你内联指定一些坐标计算使之变得简单。这是一个例子\coordinate (A) at (0, 0); \coordinate (B) at (1, 2); \coordinate (C) at ($(A)(2, 0)$); \draw (A) node [left] {A} -- (B) node [above] {B} -- (C) node [right] {C} -- cycle; \coordinate (midpoint) at ($(A)!0.5!(C)$); \draw (midpoint) -- (B); % 高度绘制高的等腰三角形注意在中点的计算中我们使用0.5表示中间点。我们可以使用任何分数。例如如果我们使用0.2我们会计算一个位于从A出发AC长度0.2倍处的点。宏和数学当内联坐标计算不够用时PGF有自己的数学引擎可以进行更复杂的计算。你还可以用它来定义宏用于参数化你的图形以便于维护。\pgfmathsetmacro{\width}{3} \pgfmathsetmacro{\height}{2} \pgfmathsetmacro{\mydistance}{3} \pgfmathsetmacro{\myangle}{60} \pgfmathsetmacro{\newx}{\mydistance * cos(\myangle)} \pgfmathsetmacro{\newy}{\mydistance * sin(\myangle)} \draw [red] (0, 0) rectangle (\width, \height); \draw [blue] (\newx, \newy) rectangle (0.5*\width, 0.5*\height);使用PGF数学引擎进行高级计算#### 循环什么编程语言会没有循环和条件语句TikZ提供这些功能让你在绘图中有更大的灵活性\foreach \rowIdx/\rowLabel in {0/A,1/B,2/C}{ \foreach \colIdx in {0,...,3}{ \def\nodenamelabel{\rowLabel-\colIdx}; \node [draw, circle, shadingball, ball colorblue] (\nodenamelabel) at (\colIdx, \rowIdx) {\color{white}{\nodenamelabel}}; } }使用循环避免重复你也可以使用条件语句但我不经常使用它们所以请参考手册。作用域你可以在tikzpicture中使用scope环境来临时改变图形的选项和样式。这非常方便例如如果你想重复一个图形但将原点移动到不同的点\coordinate (A) at (0, 0); \coordinate (B) at (1, 2); \coordinate (C) at ($(A)(2, 0)$); \draw (A) node [left] {A} -- (B) node [above] {B} -- (C) node [right] {C} -- cycle; \coordinate (midpoint) at ($(A)!0.5!(C)$); \draw (midpoint) -- (B); % 高度 \begin{scope}[shift{(3, 3)}, rotate30, colorred] \coordinate (A) at (0, 0); \coordinate (B) at (1, 2); \coordinate (C) at ($(A)(2, 0)$); \draw (A) node [left] {A} -- (B) node [above] {B} -- (C) node [right] {C} -- cycle; \coordinate (midpoint) at ($(A)!0.5!(C)$); \draw (midpoint) -- (B); % 高度 \end{scope}使用作用域移动坐标注意我们必须用花括号括住shift因为它的值包含逗号逗号用于分隔传递给大多数命令的选项。在我们传递给scope的选项中我们还可以改变图形的比例更改颜色选项如上所示并添加更多的本地自定义。一个涵盖一切的节点最后有一个简单的技巧可以把一堆图形包围在一个大框里用于说明目的。你指定一个节点并告诉它必须包含某些其他节点\foreach \rowIdx/\rowLabel in {0/A,1/B,2/C}{ \foreach \colIdx in {0,...,3}{ \def\nodenamelabel{\rowLabel-\colIdx}; \node [draw, circle, shadingball, ball colorblue] (\nodenamelabel) at (\colIdx, \rowIdx) {\color{white}{\nodenamelabel}}; } } \node [draw, rectangle, rounded corners, fit(A-0) (C-3),fillred, opacity0.3] {};轻松地将图形包围在大节点中注意在fit选项中只指定两个球形节点就足够了因为如果矩形适合对角的那两个它会自动适合所有其他节点。5、结束语我希望这趟PGF/TikZ的旋风之旅能激起你对它所有可能性的兴趣。当然我只是触及了表面。TikZ比我这里展示的功能要多得多。如果你从这篇文章中得到一个要点那就是用图形语言指定技术图形比手动绘制要好得多原因如下更好的精度矢量图形的无限分辨率更大的灵活性和自动化性更少的上下文切换最后TikZ的另一个优势是它是由与LaTeX中Beamer演示文稿类的同一人编写的所以它们配合得很好可以创建真正令人惊叹的演示文稿。请停止手动绘制图形开始编写代码吧。原文链接用 TikZ 绘制技术图形 - 汇智网