3

This vertical timeline using tikz looks great in an article but in a beamer poster the line spacing is miscalculated. The tikz code is from szantaii's answer to the question High level macros and environments based on Tikz, incorporated in this working example:

%\documentclass{article}
%\usepackage{geometry}

\documentclass{beamer}
\usepackage{beamerposter}

\usepackage{tikz}

\usetikzlibrary{arrows, calc, decorations.markings, positioning}

\makeatletter
\newenvironment{timeline}[6]{%
    % #1 is startyear
    % #2 is tlendyear
    % #3 is yearcolumnwidth
    % #4 is rulecolumnwidth
    % #5 is entrycolumnwidth
    % #6 is timelineheight

    \newcommand{\startyear}{#1}
    \newcommand{\tlendyear}{#2}

    \newcommand{\yearcolumnwidth}{#3}
    \newcommand{\rulecolumnwidth}{#4}
    \newcommand{\entrycolumnwidth}{#5}
    \newcommand{\timelineheight}{#6}

    \newcommand{\templength}{}

    \newcommand{\entrycounter}{0}

    % https://tex.stackexchange.com/questions/85528/checking-whether-or-not-a-node-has-been-previously-defined
    % https://tex.stackexchange.com/questions/37709/how-can-i-know-if-a-node-is-already-defined
    \long\def\ifnodedefined##1##2##3{%
        \@ifundefined{pgf@sh@ns@##1}{##3}{##2}%
    }

    \newcommand{\ifnodeundefined}[2]{%
        \ifnodedefined{##1}{}{##2}
    }

    \newcommand{\drawtimeline}{%
        \draw[timelinerule] (\yearcolumnwidth+5pt, 0pt) -- (\yearcolumnwidth+5pt, -\timelineheight);
        \draw (\yearcolumnwidth+0pt, -10pt) -- (\yearcolumnwidth+10pt, -10pt);
        \draw (\yearcolumnwidth+0pt, -\timelineheight+15pt) -- (\yearcolumnwidth+10pt, -\timelineheight+15pt);

        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[year] (year-\startyear) at (\yearcolumnwidth, \templength) {\startyear};

        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\tlendyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[year] (year-\tlendyear) at (\yearcolumnwidth, \templength) {\tlendyear};
    }

    \newcommand{\entry}[2]{%
        % #1 is the year
        % #2 is the entry text

        \pgfmathtruncatemacro{\lastentrycount}{\entrycounter}
        \pgfmathtruncatemacro{\entrycounter}{\entrycounter + 1}

        \ifdim \lastentrycount pt > 0 pt%
            \node[entry] (entry-\entrycounter) [below of=entry-\lastentrycount] {##2};
        \else%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \node[entry] (entry-\entrycounter) at (\yearcolumnwidth+\rulecolumnwidth+10pt, \templength) {##2};
        \fi

        \ifnodeundefined{year-##1}{%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(##1, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \draw (\yearcolumnwidth+2.5pt, \templength) -- (\yearcolumnwidth+7.5pt, \templength);
            \node[year] (year-##1) at (\yearcolumnwidth, \templength) {##1};
        }

        \draw ($(year-##1.east)+(2.5pt, 0pt)$) -- ($(year-##1.east)+(7.5pt, 0pt)$) -- ($(entry-\entrycounter.west)-(5pt,0)$) -- (entry-\entrycounter.west);
    }

    \newcommand{\plainentry}[2]{% plainentry won't print date in the timeline
        % #1 is the year
        % #2 is the entry text

        \pgfmathtruncatemacro{\lastentrycount}{\entrycounter}
        \pgfmathtruncatemacro{\entrycounter}{\entrycounter + 1}

        \ifdim \lastentrycount pt > 0 pt%
            \node[entry] (entry-\entrycounter) [below of=entry-\lastentrycount] {##2};
        \else%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \node[entry] (entry-\entrycounter) at (\yearcolumnwidth+\rulecolumnwidth+10pt, \templength) {##2};
        \fi

        \ifnodeundefined{invisible-year-##1}{%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(##1, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \draw (\yearcolumnwidth+2.5pt, \templength) -- (\yearcolumnwidth+7.5pt, \templength);
            \node[year] (invisible-year-##1) at (\yearcolumnwidth, \templength) {};
        }

        \draw ($(invisible-year-##1.east)+(2.5pt, 0pt)$) -- ($(invisible-year-##1.east)+(7.5pt, 0pt)$) -- ($(entry-\entrycounter.west)-(5pt,0)$) -- (entry-\entrycounter.west);
    }

    \begin{tikzpicture}
        \tikzstyle{entry} = [%
            align=left,%
            text width=\entrycolumnwidth,%
            node distance=10mm,%
            anchor=west]
        \tikzstyle{year} = [anchor=east]
        \tikzstyle{timelinerule} = [%
            draw,%
            decoration={markings, mark=at position 1 with {\arrow[scale=1.5]{latex'}}},%
            postaction={decorate},%
            shorten >=0.4pt]

        \drawtimeline
}
{
    \end{tikzpicture}
    \let\startyear\@undefined
    \let\tlendyear\@undefined
    \let\yearcolumnwidth\@undefined
    \let\rulecolumnwidth\@undefined
    \let\entrycolumnwidth\@undefined
    \let\timelineheight\@undefined
    \let\entrycounter\@undefined
    \let\ifnodedefined\@undefined
    \let\ifnodeundefined\@undefined
    \let\drawtimeline\@undefined
    \let\entry\@undefined
}
\makeatother


\begin{document}

\begin{timeline}{1940}{2020}{5cm}{2cm}{20cm}{15cm}

\plainentry{1941}{1941 this timeline entry is long enough to continue on a second line}
\plainentry{1946}{1946 this entry gets stepped on}
\plainentry{1947}{1947 this entry is long enough to continue on a second line and then even a third line it is quite the run-on entry that runs on and on and on do you see it run on?}
\plainentry{1947}{This is another entry for the same year}
\plainentry{1948}{1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 }
\plainentry{1951}{1951 some text}
\entry{1955}{1955 some other text}
\entry{1960}{1960 yet more text}
\entry{1970}{1970 and still more}
\entry{2015}{2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 }
\plainentry{2018}{2018 2018 2018 2018 2018 2018 2018 2018 2018 2018 2018}

\end{timeline}

\end{document}

And the result:

A vertical timeline with overlapped lines

3
  • What does '@szantaii' mean? If that code has a source, can you provide a link?
    – cfr
    Oct 9, 2019 at 22:36
  • An obvious workaround is to typeset the timeline separately, then load it from a PDF into the poster. But I will make more timelines so fixing this interaction would be better.
    – Una
    Oct 9, 2019 at 22:55
  • 1
    Okay, I figured out how to add the link.
    – Una
    Oct 10, 2019 at 1:02

1 Answer 1

3

Welcome to TeX.SE. You just need to set the node distance to an appropriate amount to get the right spacing of your labels. I made it node distance=20mm. I added the timeline to a two-column frame and it seems to be fine. You will need to play with node distance and the length of the timeline to suit your particular needs.

enter image description here

%\documentclass{article}
%\usepackage{geometry}

\documentclass{beamer}
\usepackage[size=custom,height=150,width=90,scale=1]{beamerposter}

\usepackage{tikz}

\usetikzlibrary{arrows, calc, decorations.markings, positioning}

\makeatletter
\newenvironment{timeline}[6]
{
    % #1 is startyear
    % #2 is tlendyear
    % #3 is yearcolumnwidth
    % #4 is rulecolumnwidth
    % #5 is entrycolumnwidth
    % #6 is timelineheight

    \newcommand{\startyear}{#1}
    \newcommand{\tlendyear}{#2}

    \newcommand{\yearcolumnwidth}{#3}
    \newcommand{\rulecolumnwidth}{#4}
    \newcommand{\entrycolumnwidth}{#5}
    \newcommand{\timelineheight}{#6}

    \newcommand{\templength}{}

    \newcommand{\entrycounter}{0}

    % http://tex.stackexchange.com/questions/85528/checking-whether-or-not-a-node-has-been-previously-defined
    % http://tex.stackexchange.com/questions/37709/how-can-i-know-if-a-node-is-already-defined
    \long\def\ifnodedefined##1##2##3{%
        \@ifundefined{pgf@sh@ns@##1}{##3}{##2}%
    }

    \newcommand{\ifnodeundefined}[2]{%
        \ifnodedefined{##1}{}{##2}
    }

    \newcommand{\drawtimeline}{%
        \draw[timelinerule] (\yearcolumnwidth+5pt, 0pt) -- (\yearcolumnwidth+5pt, -\timelineheight);
        \draw (\yearcolumnwidth+0pt, -10pt) -- (\yearcolumnwidth+10pt, -10pt);
        \draw (\yearcolumnwidth+0pt, -\timelineheight+15pt) -- (\yearcolumnwidth+10pt, -\timelineheight+15pt);

        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[year] (year-\startyear) at (\yearcolumnwidth, \templength) {\startyear};

        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\tlendyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[year] (year-\tlendyear) at (\yearcolumnwidth, \templength) {\tlendyear};
    }

    \newcommand{\entry}[2]{%
        % #1 is the year
        % #2 is the entry text

        \pgfmathtruncatemacro{\lastentrycount}{\entrycounter}
        \pgfmathtruncatemacro{\entrycounter}{\entrycounter + 1}

        \ifdim \lastentrycount pt > 0 pt%
        \node[entry] (entry-\entrycounter) [below of=entry-\lastentrycount] {##2};
        \else%
        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[entry] (entry-\entrycounter) at (\yearcolumnwidth+\rulecolumnwidth+10pt, \templength) {##2};
        \fi

        \ifnodeundefined{year-##1}{%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(##1, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \draw (\yearcolumnwidth+2.5pt, \templength) -- (\yearcolumnwidth+7.5pt, \templength);
            \node[year] (year-##1) at (\yearcolumnwidth, \templength) {##1};
        }

        \draw ($(year-##1.east)+(2.5pt, 0pt)$) -- ($(year-##1.east)+(7.5pt, 0pt)$) -- ($(entry-\entrycounter.west)-(5pt,0)$) -- (entry-\entrycounter.west);
    }

    \newcommand{\plainentry}[2]{% plainentry won't print date in the timeline
        % #1 is the year
        % #2 is the entry text

        \pgfmathtruncatemacro{\lastentrycount}{\entrycounter}
        \pgfmathtruncatemacro{\entrycounter}{\entrycounter + 1}

        \ifdim \lastentrycount pt > 0 pt%
        \node[entry] (entry-\entrycounter) [below of=entry-\lastentrycount] {##2};
        \else%
        \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(\startyear, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
        \node[entry] (entry-\entrycounter) at (\yearcolumnwidth+\rulecolumnwidth+10pt, \templength) {##2};
        \fi

        \ifnodeundefined{invisible-year-##1}{%
            \pgfmathsetlengthmacro{\templength}{neg(add(multiply(subtract(##1, \startyear), divide(subtract(\timelineheight, 25), subtract(\tlendyear, \startyear))), 10))}
            \draw (\yearcolumnwidth+2.5pt, \templength) -- (\yearcolumnwidth+7.5pt, \templength);
            \node[year] (invisible-year-##1) at (\yearcolumnwidth, \templength) {};
        }

        \draw ($(invisible-year-##1.east)+(2.5pt, 0pt)$) -- ($(invisible-year-##1.east)+(7.5pt, 0pt)$) -- ($(entry-\entrycounter.west)-(5pt,0)$) -- (entry-\entrycounter.west);
    }

    \begin{tikzpicture}
    \tikzstyle{entry} = [%
    align=left,%
    text width=\entrycolumnwidth,%
    node distance=20mm,%     <-- Adjust this to get wider spacing of the labels
    anchor=west]
    \tikzstyle{year} = [anchor=east]
    \tikzstyle{timelinerule} = [%
    draw,%
    decoration={markings, mark=at position 1 with {\arrow[scale=1.5]{latex'}}},%
    postaction={decorate},%
    shorten >=0.4pt]

    \drawtimeline
}
{
    \end{tikzpicture}
    \let\startyear\@undefined
    \let\tlendyear\@undefined
    \let\yearcolumnwidth\@undefined
    \let\rulecolumnwidth\@undefined
    \let\entrycolumnwidth\@undefined
    \let\timelineheight\@undefined
    \let\entrycounter\@undefined
    \let\ifnodedefined\@undefined
    \let\ifnodeundefined\@undefined
    \let\drawtimeline\@undefined
    \let\entry\@undefined
}
\makeatother

\begin{document}

\begin{frame}{}

  \begin{columns}[t]

    \begin{column}{.45\linewidth}
      \begin{block}{FOOBAR}
         \begin{timeline}{1940}{2020}{5cm}{2cm}{20cm}{20cm}

         \plainentry{1941}{1941 this timeline entry is long enough to continue on a second line}
         \plainentry{1946}{1946 this entry gets stepped on}
         \plainentry{1947}{1947 this entry is long enough to continue on a second line and then even a third line it is quite the run-on entry that runs on and on and on do you see it run on?}
         \plainentry{1947}{This is another entry for the same year}
         \plainentry{1948}{1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 }
         \plainentry{1951}{1951 some text}
         \entry{1955}{1955 some other text}
         \entry{1960}{1960 yet more text}
         \entry{1970}{1970 and still more}
         \entry{2015}{2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 }
         \plainentry{2018}{2018 2018 2018 2018 2018 2018 2018 2018 2018 2018 2018}

         \end{timeline}
      \end{block}
    \end{column}

    \begin{column}{.45\linewidth}
      \begin{block}{FOOBAR}
       foobar
      \end{block}
    \end{column}

  \end{columns}

\end{frame}

\end{document}
3
  • I see. Thanks! The node distance (label depth) is explicit and equal for all labels, regardless of the number of lines of text in the label. The node distance could be calculated.
    – Una
    Oct 10, 2019 at 2:16
  • Yes, the node distance is explicitly set here: \node[entry] (entry-\entrycounter) [below of=entry-\lastentrycount] {##2};. You need a different solution to stack the nodes without spaces. See @Zarko's first solution here: tex.stackexchange.com/a/508240. It puts the labels on a chain. TorbjørnT.'s answer also updates the timeline code you used to replace deprecated syntax.
    – Ross
    Oct 10, 2019 at 4:02
  • Oh, super! Thank you. That Q&A thread is new to me or I would not have started this one. I need a few more rep points before I can comment, vote, or do anything much over there.
    – Una
    Oct 10, 2019 at 17:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .