甘特图 latex 功能真的很复杂。我只想要一个像这样的简单小东西,用于可视化调度算法
我该怎么做?
预计到达时间:我代码来自这里并添加颜色。
\definecolor{p1}{HTML}{5780dc}
\definecolor{p2}{HTML}{dc0404}
\definecolor{p3}{HTML}{1ec81e}
\definecolor{p4}{HTML}{8424ac}
\definecolor{p5}{HTML}{e68142}
\begin{tikzpicture}[
node distance = 0pt,
G/.style = {draw, color=white, text width=2*#1mm, align=center,
inner xsep=0pt, outer sep=0pt,
anchor=south west},
tck/.style = {font=\scriptsize, below}
]
\newlength{\prev}
\foreach \n/\i [remember=\i as \j (initially 0),
evaluate=\i as \k using \i-\j] in {
1/2, 2/3, 3/11, 4/15, 5/20
}
{
\node[G=\k, fill=p\n] at (\j/5,0) {$P_\n$};
\node[tck] at (\i/5,0) {\i};
\ifnum\j=0
\node[tck] at (0,0) {\j};
\fi
}
\end{tikzpicture}
总体来说还不错,但如果宽度只有 1,怎么办?太窄了,文本会被截断。
我该如何改变它以避免这种情况?我想让整个东西变宽,而不是让文本变小。
另外,有没有办法有一个 sum 变量?每次都可以将数字添加到某个变量中,以便变量是前面数字的总和?这样输入就可以是:
{p2/2, p1/1, p4/4, p5/5, p3/8}
答案1
这是关于一个可自定义的简单甘特图的建议(不过可能有点过头了)。您可以定义一组要循环的颜色,自定义刻度的宽度和高度以及位置,还可以设置一个阈值来决定标签是放在节点内还是作为图钉。当前的一个缺点是颜色的定义无法限定范围。
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\newif\ifsimplegantttickpositionbelow
\tikzset{
pics/simple gantt/.style={
code={
\ifsimplegantttickpositionbelow
\path[/tikz/simple gantt/tick] (0,0) --
++(0,{-1*\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{0}};
\else
\path[/tikz/simple gantt/tick] (0,\pgfkeysvalueof{/tikz/simple gantt/height}) --
++(0,{\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{0}};
\fi
\foreach \n/\x [count=\i, remember=\x as \lastx (initially 0)] in {#1} {
\ifsimplegantttickpositionbelow
\path[/tikz/simple gantt/tick] ({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},0) --
++(0,{-1*\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{\x}};
\else
\path[/tikz/simple gantt/tick] ({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},\pgfkeysvalueof{/tikz/simple gantt/height}) --
++(0,{\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{\x}};
\fi
\pgfmathparse{int(mod(\i - 1, \pgfkeysvalueof{/tikz/simple gantt/color cycle length}) + 1)}
\global\pgfkeyslet{/tikz/simple gantt/color cycle step}{\pgfmathresult}
\path[
/tikz/simple gantt/box,
fill={simple gantt color \pgfkeysvalueof{/tikz/simple gantt/color cycle step}},
]
({\lastx*\pgfkeysvalueof{/tikz/simple gantt/width unit}},0) rectangle
({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},\pgfkeysvalueof{/tikz/simple gantt/height})
\pgfextra{\pgfmathparse{\x - \lastx}}
\ifdim\pgfmathresult pt < \pgfkeysvalueof{/tikz/simple gantt/label as pin if value below} pt\relax
node[/tikz/simple gantt/label, pin={[/tikz/simple gantt/label pin]\pgfkeysvalueof{/tikz/simple gantt/label pin angle}:\n}] {}
\else
node[/tikz/simple gantt/label] {\n}
\fi ;
}
}
},
simple gantt/color cycle length/.initial={0},
simple gantt/color cycle step/.initial={1},
simple gantt/color cycle/.code={
\foreach \c [count=\i] in {#1} {
\xglobal\colorlet{simple gantt color \i}{\c}
\global\pgfkeyslet{/tikz/simple gantt/color cycle length}{\i}
}
},
simple gantt/height/.initial={1cm},
simple gantt/width unit/.initial={1cm},
simple gantt/box/.style={},
simple gantt/label/.style={pos=0.5},
simple gantt/label pin/.style={above, pin edge={black, thin}, pin distance=0.5cm},
simple gantt/label pin angle/.initial={90},
simple gantt/label as pin if value below/.initial={1.5},
simple gantt/tick/.style={draw},
simple gantt/tick label/.style={below},
simple gantt/tick position/.is choice,
simple gantt/tick position/above/.code={\simplegantttickpositionbelowfalse},
simple gantt/tick position/below/.code={\simplegantttickpositionbelowtrue},
simple gantt/tick position={below},
simple gantt/tick length/.initial={5pt},
simple gantt/color cycle={blue!50, red!50, green!50},
}
\begin{document}
\begin{tikzpicture}
\tikzset{
simple gantt/.cd,
width unit=0.33cm,
box/.style={draw},
}
\pic at (0,0) {simple gantt={$P_1$/2, $P_2$/3, $P_3$/11, $P_4$/15, $P_5$/20}};
\tikzset{
simple gantt/.cd,
height=0.75cm,
color cycle={yellow, orange, cyan, magenta},
label pin angle={270},
label pin/.append style={below},
tick position={above},
tick label/.append style={above},
label as pin if value below={4},
}
\pic at (0,-3) {simple gantt={A/1, B/3, C/9, D/10, E/20, F/25}};
\end{tikzpicture}
\end{document}
使用类似 的方法可以更轻松地确定颜色范围color cycle/.list={}
。但是,为了正确循环颜色,我需要此列表的长度,但我发现很难正确存储它。也许,使用 ID 先于其他列表定义颜色列表,然后pic
使用 ID 为每个列表引用定义颜色列表会更容易。
无论如何,我找到了一种以某种方式确定颜色列表范围的方法,但我很确定这不是最简单、最直接的方法:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\newif\ifsimplegantttickpositionbelow
\newcounter{simpleganttcolorindex}
\tikzset{
pics/simple gantt/.style={
/tikz/simple gantt/color cycle get length/.expanded={\pgfkeysvalueof{/tikz/simple gantt/color cycle list}},
code={
\ifsimplegantttickpositionbelow
\path[/tikz/simple gantt/tick] (0,0) --
++(0,{-1*\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{0}};
\else
\path[/tikz/simple gantt/tick] (0,\pgfkeysvalueof{/tikz/simple gantt/height}) --
++(0,{\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{0}};
\fi
\foreach \n/\x [count=\i, remember=\x as \lastx (initially 0)] in {#1} {
\ifsimplegantttickpositionbelow
\path[/tikz/simple gantt/tick] ({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},0) --
++(0,{-1*\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{\x}};
\else
\path[/tikz/simple gantt/tick] ({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},\pgfkeysvalueof{/tikz/simple gantt/height}) --
++(0,{\pgfkeysvalueof{/tikz/simple gantt/tick length}})
node[/tikz/simple gantt/tick label] {\pgfmathprintnumber{\x}};
\fi
\pgfmathparse{int(mod(\i - 1, \pgfkeysvalueof{/tikz/simple gantt/color cycle length}) + 1)}
\pgfkeyslet{/tikz/simple gantt/color cycle step}{\pgfmathresult}
\path[
/tikz/simple gantt/box,
fill={simple gantt color \pgfkeysvalueof{/tikz/simple gantt/color cycle step}},
]
({\lastx*\pgfkeysvalueof{/tikz/simple gantt/width unit}},0) rectangle
({\x*\pgfkeysvalueof{/tikz/simple gantt/width unit}},\pgfkeysvalueof{/tikz/simple gantt/height})
\pgfextra{\pgfmathparse{\x - \lastx}}
\ifdim\pgfmathresult pt < \pgfkeysvalueof{/tikz/simple gantt/label as pin if value below} pt\relax
node[/tikz/simple gantt/label, pin={[/tikz/simple gantt/label pin]\pgfkeysvalueof{/tikz/simple gantt/label pin angle}:\n}] {}
\else
node[/tikz/simple gantt/label] {\n}
\fi ;
}
}
},
simple gantt/.cd,
color cycle step/.initial={1},
color cycle list/.initial={},
color cycle length/.initial={1},
color cycle loop/.code={
\stepcounter{simpleganttcolorindex}
},
color cycle get length/.code={
\setcounter{simpleganttcolorindex}{0}
\pgfkeys{
/tikz/simple gantt/color cycle loop/.list={#1},
/tikz/simple gantt/color cycle length={\thesimpleganttcolorindex},
}
},
color cycle define colors/.code={
\stepcounter{simpleganttcolorindex}
\colorlet{simple gantt color \thesimpleganttcolorindex}{#1}
},
color cycle/.code={
\setcounter{simpleganttcolorindex}{0}
\pgfkeys{
/tikz/simple gantt/color cycle list={#1},
/tikz/simple gantt/color cycle define colors/.list={#1},
}
},
height/.initial={1cm},
width unit/.initial={1cm},
box/.style={},
label/.style={pos=0.5},
label pin/.style={above, pin edge={black, thin}, pin distance=0.5cm},
label pin angle/.initial={90},
label as pin if value below/.initial={1.5},
tick/.style={draw},
tick label/.style={below},
tick position/.is choice,
tick position/above/.code={\simplegantttickpositionbelowfalse},
tick position/below/.code={\simplegantttickpositionbelowtrue},
tick position={below},
tick length/.initial={5pt},
color cycle={blue!50, red!50, green!50},
}
\begin{document}
\begin{tikzpicture}
\tikzset{
simple gantt/.cd,
width unit=0.33cm,
box/.style={draw},
}
\pic at (0,0) {simple gantt={$P_1$/2, $P_2$/3, $P_3$/11, $P_4$/15, $P_5$/20}};
\begin{scope}
\tikzset{
simple gantt/.cd,
height=0.75cm,
color cycle={yellow, orange, cyan, magenta},
label pin angle={270},
label pin/.append style={below},
tick position={above},
tick label/.append style={above},
label as pin if value below={4},
}
\pic at (0,-3) {simple gantt={A/1, B/3, C/9, D/10, E/20, F/25}};
\end{scope}
\pic at (0,-6) {simple gantt={A/1, B/3, C/9, D/10, E/20, F/25}};
\end{tikzpicture}
\end{document}
答案2
我使用 Mathcha 完成的 MWE 与图像的原始颜色一起添加。
\documentclass[a4paper,12pt]{article}
\usepackage{tikz}
\begin{document}
\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1]
%uncomment if require: \path (0,467); %set diagram left start at 0, and has height of 467
%Shape: Rectangle [id:dp007554265052235776]
\draw [draw opacity=0][fill={rgb, 255:red, 87; green, 128; blue, 220 } ,fill opacity=1 ] (131,123) -- (201,123) -- (201,163) -- (131,163) -- cycle ;
%Shape: Rectangle [id:dp431468506218484]
\draw [draw opacity=0][fill={rgb, 255:red, 220; green, 4; blue, 4 } ,fill opacity=1 ] (201,123) -- (231.33,123) -- (231.33,163) -- (201,163) -- cycle ;
%Shape: Rectangle [id:dp2215419221563808]
\draw [draw opacity=0][fill={rgb, 255:red, 30; green, 200; blue, 30 } ,fill opacity=1 ] (231.33,123) -- (351.33,123) -- (351.33,163) -- (231.33,163) -- cycle ;
%Shape: Rectangle [id:dp3305984746556416]
\draw [draw opacity=0][fill={rgb, 255:red, 132; green, 36; blue, 172 } ,fill opacity=1 ] (351.33,123) -- (401.33,123) -- (401.33,163) -- (351.33,163) -- cycle ;
%Shape: Rectangle [id:dp2743597291571982]
\draw [draw opacity=0][fill={rgb, 255:red, 230; green, 129; blue, 66 } ,fill opacity=1 ] (401.33,123) -- (490.33,123) -- (490.33,163) -- (401.33,163) -- cycle ;
% Text Node
\draw (127,164) node [anchor=north west][inner sep=0.75pt] [align=left] {0};
% Text Node
\draw (194,164) node [anchor=north west][inner sep=0.75pt] [align=left] {7};
% Text Node
\draw (225.33,164) node [anchor=north west][inner sep=0.75pt] [align=left] {10};
% Text Node
\draw (341,164) node [anchor=north west][inner sep=0.75pt] [align=left] {22};
% Text Node
\draw (393,164) node [anchor=north west][inner sep=0.75pt] [align=left] {27};
% Text Node
\draw (477,164) node [anchor=north west][inner sep=0.75pt] [align=left] {36\\};
% Text Node
\draw (149,137) node [anchor=north west][inner sep=0.75pt] [align=left] {\textcolor[rgb]{1,1,1}{P1 \ \ \ \ \ \ P2 \ \ \ \ \ \ \ \ \ \ P3 \ \ \ \ \ \ \ \ \ \ \ P4 \ \ \ \ \ \ \ \ \ P5 \ \ \ }};
\end{tikzpicture}
\end{document}
答案3
我以 Sebastiano 的代码为基础,但对其进行了简化:
\begin{document}
\definecolor{p1}{HTML}{5780dc}
\definecolor{p2}{HTML}{dc0404}
\definecolor{p3}{HTML}{1ec81e}
\definecolor{p4}{HTML}{8424ac}
\definecolor{p5}{HTML}{e68142}
\begin{tikzpicture}
\foreach \n/\i [remember=\i as \j (initially 0)] in {1/2, 2/3, 3/11, 4/15, 5/20}
{
\draw[fill=p\n] (\j/2,0) rectangle node{\textcolor[rgb]{1,1,1}{$P_\n$}} (\i/2,1);
\draw (\i/2,-0.1) node [anchor=north][inner sep=0.75pt][align=center] {\i};
}
\draw (0,-0.1) node [anchor=north][inner sep=0.75pt][align=center] {0};
\end{tikzpicture}
\end{document}
这样可以最轻松地替换图表中的不同值。例如:
{1/2, 2/3, 3/11, 4/15, 5/20}
{1/2, 2/3, 3/5, 4/7, 5/9, 3/11, 4/13, 5/15, 3/17, 5/18, 3/20}
答案4
如果您想要一些简单的东西,您可以尝试{tabular}
用彩色单元格绘制。
使用经典的{tabular}
和colortbl
,绘制表格并控制单元格宽度会很容易。但是,放置标签会稍微复杂一些。使用{NiceTabular}
(nicematrix
类似于经典的{tabular}
),您可以将标签放在 Tikz 中所需的位置(在所谓的 中\CodeAfter
)。
\documentclass{article}
\usepackage{nicematrix,tikz}
\begin{document}
\NiceMatrixOptions{cell-space-top-limit=1mm}
\begin{NiceTabular}{wc{1cm} c w{c}{10mm} w{c}{10mm} w{c}{2cm}}[colortbl-like]
\RowStyle[color=white]{\sffamily}
\cellcolor{blue!70} P1 &
\cellcolor{red!70} P2 &
\cellcolor{green!70} P3 &
\cellcolor{blue!70} P4 &
\cellcolor{magenta!70} P5
\CodeAfter
\begin{tikzpicture} [below] \small
\node at (2-|1) { 0 } ;
\node at (2-|2) { 7 } ;
\node at (2-|3) { 10 } ;
\node at (2-|4) { 22 } ;
\node at (2-|5) { 27 } ;
\node at (2-|6) { 36 } ;
\end{tikzpicture}
\end{NiceTabular}
\end{document}