在纸上的多行上创建一个时间线

在纸上的多行上创建一个时间线

在浏览 tex.SE 时,我看到在这里回答,真的很惊讶它看起来如此漂亮和干净。现在我面临的问题略有不同,而且我对 tikz 不太熟悉(我只知道如何做一些简单的事情),所以我无法真正调整代码以适应我的问题。

假设您有一张 A4 纸的空间,我想将一条时间线分成 13 条单独的“子线”,每条“子线”代表一个月,并从纸上的新行开始。然后为时间线上的每个事件创建一个彩色方块,并在该方块中写下事件的名称。

为了使它更清楚一点,这里有一张图片。

在此处输入图片描述

目标是创建一个新的命令,类似于提到的帖子,并包含以下信息:

\event{dd.mm.}{dd.mm.}{text}{color}{number}

其中第一个参数是事件的开始日期,第二个参数是结束日期。第三个参数应表示方块内的文本,第四个参数是方块的颜色,由于一些事件重叠,我还需要将事件放置在不同高度的选项,因此是最后一个参数。

对我来说这里最大的两个问题是:

  1. 我不知道如何创建一条连续的线,然后将其分成十三段,每段占一行。
  2. 有些活动只有一天,所以文本不可能放得下。这些情况需要一些特殊处理,但我不知道如何实现这样的事情。

或者,我也可以单独创建十三条时间线,然后将它们放在一张图中,这样至少可以解决第一个问题。当然,也可以选择直接创建,用箭头作为时间线,然后手工绘制每个方块、文本等,但由于条目将来可能会发生很大变化,这似乎不是最佳选择。


很抱歉我没有可以运行的 MWE,但说实话我有点不知道如何创建这样的命令。


编辑: 经过一些尝试,我得出了以下结论:

\documentclass[12pt]{article}
\usepackage[a4paper, margin=1cm]{geometry}
\usepackage{amsmath}
\usepackage{xstring}
\usepackage{tikz}
\usetikzlibrary{fit, calc}
\pagestyle{empty} 

\newcommand{\anno}{1} % starting year
\newcommand{\target}{31} % ending year
\newcommand{\alto}{3} % height

\pgfmathsetmacro{\myend}{\target+1-\anno}
\pgfmathsetmacro{\myspacing}{16/(\target-1-\anno)}


\newcommand{\eventpoint}[4]{    
    \StrBefore{#1}{/}[\dstart]%x1=day_start
    \StrBehind{#1}{/}[\mstart]%y1=month_start
    \StrBefore{#2}{/}[\dend]%x2=day_end
    \StrBehind{#2}{/}[\mend]%y2=month_end
    \pgfmathsetmacro{\mmstart}{((13-\mstart)*4)}
    \pgfmathsetmacro{\mmend}{((13-\mend)*4)}
    \ifthenelse{\mstart = \mend}
               {\filldraw[fill=#3!50, draw=#3,] (\dstart, \mmstart ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#4};}
               {\filldraw[fill=#3!50, draw=#3,] (\dstart, \mmstart ) rectangle (31, \mmstart+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#4};
               \filldraw[fill=#3!50, draw=#3,] (0, \mmend ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#4};};
}

\begin{document}
\begin{tikzpicture}[x=\myspacing cm,y=5mm]
\centering

%creating the sublines needed and formating them
\foreach \y in {0,4,8,12,16,20,24,28,32,36,40,44,48}{
\draw[|->, -latex] (-.5,\y) -- (\myend+.5,\y);
\path (0,0) -- (0,\alto);
\foreach \x [evaluate=\x as \day using int(\x)] in {0,10,20,30}{ 
    \draw (\x,\y) node[below=7pt,font=\footnotesize] {$\day$}; 
    \draw (\x,\y -.2) -- (\x,\y +.2);
    \draw[loosely dotted] (\x,\y +.2) -- (\x,\y+ \alto-0.5);
}
\foreach \tick in {0,...,\myend}{
    \draw (\tick,\y +.1) -- (\tick,\y -.1);
}
}

%trying to add the events
\eventpoint{15/7}{25/7}{green}{test}
\eventpoint{17/8}{19/9}{red}{test 2}


\end{tikzpicture}
\end{document}

代码无法正常工作,但我怀疑这是由于我错误使用造成的\ifthenelse。希望有人可以修复这个问题。

答案1

\ifthenelse代码中的 可以用标准 轻松实现。\ifnum此外,我通过重用 强大的 key/val 功能重新实现了日期设置/解析pgf

\documentclass[12pt]{article}
\usepackage[a4paper, margin=1cm]{geometry}
\usepackage{tikz}
\pagestyle{empty}

\newcommand{\anno}{1} % starting year
\newcommand{\target}{31} % ending year
\newcommand{\alto}{3} % height

\tikzset{
    start date/.code args = {#1/#2}{
        \def\dstart{#1}
        \def\mstart{#2}
    },
    end date/.code args = {#1/#2}{
        \def\dend{#1}
        \def\mend{#2}
    },
    event color/.style = {
        fill=#1!50, draw=#1,
    },
}

\pgfmathsetmacro{\myend}{\target+1-\anno}
\pgfmathsetmacro{\myspacing}{16/(\target-1-\anno)}


\newcommand{\eventpoint}[2][]{
    \begin{scope}[#1]
    \pgfmathsetmacro{\mmstart}{((13-\mstart)*4)}
    \pgfmathsetmacro{\mmend}{((13-\mend)*4)}
    \ifnum\mstart=\mend
       \filldraw (\dstart, \mmstart ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
    \else
       \filldraw (\dstart, \mmstart ) rectangle (31, \mmstart+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
      \filldraw (0, \mmend ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
    \fi
    \end{scope}
}

\begin{document}
\centering
\begin{tikzpicture}[x=\myspacing cm,y=5mm]

%creating the sublines needed and formating them
\foreach \y in {0,4,8,12,16,20,24,28,32,36,40,44,48}{
\draw[|->, -latex] (-.5,\y) -- (\myend+.5,\y);
\path (0,0) -- (0,\alto);
\foreach \x [evaluate=\x as \day using int(\x)] in {0,10,20,30}{
    \draw (\x,\y) node[below=7pt,font=\footnotesize] {$\day$};
    \draw (\x,\y -.2) -- (\x,\y +.2);
    \draw[loosely dotted] (\x,\y +.2) -- (\x,\y+ \alto-0.5);
}
\foreach \tick in {0,...,\myend}{
    \draw (\tick,\y +.1) -- (\tick,\y -.1);
}
}

%trying to add the events
\eventpoint[start date=15/7,end date=25/7,event color=green]{test}
\eventpoint[start date=17/8,end date=19/9,event color=red,yshift=5pt]{test 2} % shift just to show you can hook into standard tikz keys to change the event's features ad-hoc

\end{tikzpicture}
\end{document}

通过使用范围的键定义日期,您可以获得许多好处:

  • 提高可读性(无需猜测参数顺序)
  • 提供默认值或替代方案的可能性(练习:实现duration=months可以替代使用的键end date
  • 能够为每个事件指定临时 tikz 密钥
  • 轻松扩展附加按键
  • 解析是通过匹配参数中的分隔符来完成的

可以进行的其他改进:您可以定义设置annotargetalto参数的键。

\documentclass[12pt]{article}
\usepackage[a4paper, margin=1cm]{geometry}
\usepackage{tikz}
\pagestyle{empty}

% \newcommand{\anno}{1} % starting year
% \newcommand{\target}{31} % ending year
% \newcommand{\alto}{3} % height

\tikzset{
    anno/.store in=\anno,
    target/.store in=\target,
    alto/.store in=\alto,
    start date/.code args = {#1/#2}{
        \def\dstart{#1}
        \def\mstart{#2}
    },
    end date/.code args = {#1/#2}{
        \def\dend{#1}
        \def\mend{#2}
    },
    event color/.style = {
        fill=#1!50, draw=#1,
    },
    anno=1, target=1, alto=1,% here are the defaults
    auto x/.style={x=16/(\target-1-\anno)*1cm},
}



\newcommand{\eventpoint}[2][]{
    \begin{scope}[#1]
    \pgfmathsetmacro{\mmstart}{((13-\mstart)*4)}
    \pgfmathsetmacro{\mmend}{((13-\mend)*4)}
    \ifnum\mstart=\mend
       \filldraw (\dstart, \mmstart ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
    \else
       \filldraw (\dstart, \mmstart ) rectangle (31, \mmstart+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
      \filldraw (0, \mmend ) rectangle (\dend, \mmend+1) node [font=\scriptsize, text centered, midway, inner sep=0pt] {#2};
    \fi
    \end{scope}
}

\begin{document}
\centering
\begin{tikzpicture}[
    anno=1, target=31, alto=3,
    auto x, y=5mm,
]

\pgfmathsetmacro{\myend}{\target+1-\anno}

%creating the sublines needed and formating them
\foreach \y in {0,4,8,12,16,20,24,28,32,36,40,44,48}{
\draw[|->, -latex] (-.5,\y) -- (\myend+.5,\y);
\path (0,0) -- (0,\alto);
\foreach \x [evaluate=\x as \day using int(\x)] in {0,10,20,30}{
    \draw (\x,\y) node[below=7pt,font=\footnotesize] {$\day$};
    \draw (\x,\y -.2) -- (\x,\y +.2);
    \draw[loosely dotted] (\x,\y +.2) -- (\x,\y+ \alto-0.5);
}
\foreach \tick in {0,...,\myend}{
    \draw (\tick,\y +.1) -- (\tick,\y -.1);
}
}

%trying to add the events
\eventpoint[start date=15/7,end date=25/7,event color=green]{test}
\eventpoint[start date=17/8,end date=19/9,event color=red,yshift=5pt]{test 2}

\end{tikzpicture}
\end{document}

在此处输入图片描述

如果你想扩展活动的外观,强烈推荐

将产生事件的代码包装到pic定义中(参见手册)。

答案2

用 Mathcha 回答了一下。作品不是最好的,但与图片相似。

在此处输入图片描述

\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,300); %set diagram left start at 0, and has height of 300
\draw  [color={rgb, 255:red, 0; green, 0; blue, 0 }  ,draw opacity=1 ][fill={rgb, 255:red, 239; green, 100; blue, 215 }  ,fill opacity=0.86 ] (381,48.33) -- (459,48.33) -- (459,80.33) -- (381,80.33) -- cycle ;
\draw    (101.33,81.67) -- (459.83,80.67) ;
\draw [shift={(461.83,80.67)}, rotate = 539.8399999999999] [color={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.75]    (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29)   ;
\draw    (100.67,151) -- (459.17,150.01) ;
\draw [shift={(461.17,150)}, rotate = 539.8399999999999] [color={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.75]    (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29)   ;
\draw    (100.67,140.5) -- (100.67,161.5) ;
\draw    (101.33,71.16) -- (101.33,92.17) ;
\draw    (201.33,72.16) -- (201.33,93.17) ;
\draw    (300.33,72.16) -- (300.33,93.17) ;
\draw    (399.33,72.16) -- (399.33,93.17) ;
\draw    (201.33,140.16) -- (201.33,161.17) ;
\draw    (300.33,139.16) -- (300.33,160.17) ;
\draw    (400.33,137.16) -- (400.33,158.17) ;
\draw  [color={rgb, 255:red, 0; green, 0; blue, 0 }  ,draw opacity=1 ][fill={rgb, 255:red, 126; green, 211; blue, 33 }  ,fill opacity=1 ] (139,49.33) -- (242,49.33) -- (242,81.33) -- (139,81.33) -- cycle ;
\draw  [color={rgb, 255:red, 0; green, 0; blue, 0 }  ,draw opacity=1 ][fill={rgb, 255:red, 248; green, 231; blue, 28 }  ,fill opacity=1 ] (219,17.33) -- (322,17.33) -- (322,49.33) -- (219,49.33) -- cycle ;
\draw  [color={rgb, 255:red, 0; green, 0; blue, 0 }  ,draw opacity=1 ][fill={rgb, 255:red, 239; green, 100; blue, 215 }  ,fill opacity=0.86 ] (100.67,119) -- (159.5,119) -- (159.5,151) -- (100.67,151) -- cycle ;
\draw    (341.33,140.16) -- (341.33,161.17) ;
\draw    (341.33,140.16) -- (374.33,120.5) ;
\draw (70,74) node  [align=left] {Apr.};
\draw (70,147) node  [align=left] {May};
\draw (101,102) node  [align=left] {1};
\draw (200,103) node  [align=left] {10};
\draw (299,102) node  [align=left] {20};
\draw (400,101) node  [align=left] {30};
\draw (102,172) node  [align=left] {1};
\draw (201,173) node  [align=left] {10};
\draw (300,172) node  [align=left] {20};
\draw (401,171) node  [align=left] {30};
\draw (189,66) node  [align=left] {event 1};
\draw (266,33) node  [align=left] {event 2};
\draw (420,64) node  [align=left] {event 3};
\draw (129,135) node  [align=left] {event 3};
\draw (405,119) node  [align=left] {event 4};
\end{tikzpicture}
\end{document}

相关内容