我有这个生成流程甘特图的代码:
\usetikzlibrary{shadows,arrows,positioning}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
proc/.style={draw=black, fill=blue!15, drop shadow},
}
\node [draw, proc, minimum width=3em] (p2) {P2};
\node [draw, proc, minimum width=3em, right=0em of p2.east, anchor=west] (p3) {P3};
\node [draw, proc, minimum width=24em, right=0em of p3.east, anchor=west] (p1) {P1};
\node [below=of p2.west] {0} edge [draw] (p2.west);
\node [below=of p2.east] {3} edge [draw] (p2.east);
\node [below=of p3.east] {6} edge [draw] (p3.east);
\node [below=of p1.east] {30} edge [draw] (p1.east);
\end{tikzpicture}
输出:
我可以在这里看到一种模式,我可以想象将参数(例如p2/3,p3/3,p1/24
)传递给某个使用某种 for 循环自动生成代码的命令。不幸的是,我的 TikZ/LaTeX 技能远远低于这个水平。有人能帮我开始自动化吗?
答案1
尝试这个:
\newcommand{\gantt}[1]{
\newcounter{ganttnum}
\setcounter{ganttnum}{0}
\foreach \i/\j in {#1}{
\draw (\theganttnum em,0)node [proc, minimum width=\j em, anchor=south west] (\i) {\i};
\draw (\theganttnum em,0) -- ++(0,-0.5) node[below]{\theganttnum};
\addtocounter{ganttnum}{\j}
}
\draw (\theganttnum em,0) -- ++(0,-0.5) node[below]{\theganttnum};
}
\begin{tikzpicture}[scale=0.75,transform shape]
\gantt{P2/3,P3/3,P1/24}
\end{tikzpicture}
\begin{tikzpicture}[scale=0.75,transform shape]
\gantt{A1/3,A2/10,A3/14,A5/3,A4/3}
\end{tikzpicture}
它创建一个接受 1 个参数的新命令,该参数应为以逗号分隔的形式的列表P1/3,P2/5,P3/12
。每个项目都有两部分:节点名称(之前/
和之后的节点宽度/
)。
这允许您添加任意数量的节点,具有任意名称和宽度。
对代码进行一些解释:
Tikz'\foreach
可以进行多次循环,例如,A/1, B/2, ...
这对于在循环节点时保持节点的名称和宽度一致非常有用。
我首先将计数器gantt
设置为0
。循环中的每个步骤都会将在该步骤中添加的节点的宽度添加到此计数器中,因此可以使用计数器来确定下一个节点应该在哪里。
答案2
你可以从此代码开始
\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadows,arrows,positioning}
\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
proc/.style={draw=black, fill=blue!15, drop shadow},
}
\node [draw, proc, minimum width=3em] (p2) {P2};
\foreach \i/\j/\k in {3/2/3,1/3/24}
\node [draw, proc, minimum width=\k em, right=0em of p\j.east, anchor=west] (p\i) {P\i};
\node [below=of p2.west] {0} edge [draw] (p2.west);
\foreach \i/\j in {2/3,3/6,1/30}
\node [below=of p\i.east] {\j} edge [draw] (p\i.east);
\end{tikzpicture}
\end{document}
更新版本。相同的循环将绘制节点和标签,计数器将负责节点的初始位置。循环结束后,将绘制 0 标记。
\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadows,arrows,positioning}
\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
proc/.style={draw=black, fill=blue!15, drop shadow},
}
\newcounter{pos}
\setcounter{pos}{0}
\foreach \process/\width in {2/3,3/3,1/24}
{
\node [draw, proc, minimum width=\width em, anchor=west] (p\process) at (\thepos em,0) {P\process};
\addtocounter{pos}{\width}
\node [below=of p\process.east] {\thepos} edge [draw] (p\process.east);
}
\node [below=of p2.west] {0} edge [draw] (p2.west);
\end{tikzpicture}
\end{document}