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

  • What does '@szantaii' mean? If that code has a source, can you provide a link? – cfr Oct 9 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 at 22:55
  • 1
    Okay, I figured out how to add the link. – Una Oct 10 at 1:02
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}
  • 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 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 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 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.