4

I'm showing slides where I show a time evolution by going through snapshots. Each snapshot corresponds to a specific time.

I'd like to show a time arrow (vertically on the side) with bullets corresponding to each of the time points (unequally spaced). On each overlay, one of these bullets is solid filled and the current time is specified, whereas the other bullets are open (empty circles).

I think I can do the unaminated version quite easily with tikz, but I am not sure how to adjust the style of elements and presence of node text depending on overlay number.

Here's a MWE for a static timearrow:

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}
  \def\axscale{-0.02}
  \def\thex{0}
  \def\they{0}
  \def\prevy{0}
  \def\times{{-5,2, 12, 22, 32, 44, 76, 116, 182, 300,307}}
  \def\maxt{9}
  \foreach \it in {1,...,\maxt} {
        \pgfmathparse{\axscale*\times[\it-1]}
        \pgfmathsetmacro{\prevy}{\pgfmathresult}
        \pgfmathparse{\axscale*\times[\it]}
        \pgfmathsetmacro{\they}{\pgfmathresult}
        \draw[-{Circle[open]}] (\thex,\prevy) -- (\thex,\they);
        \node[right,anchor=west] at (\thex,\they) {
            $t=\pgfmathparse{\times[\it]}
            \pgfmathprintnumber[    % Print the result
                fixed,
                fixed zerofill,
                precision=0,
                assume math mode=true
            ]{\pgfmathresult}
            $};
  }
  \pgfmathparse{\axscale*\times[\maxt]}
  \pgfmathsetmacro{\prevy}{\pgfmathresult}
  \pgfmathparse{\axscale*\times[\maxt+1]}
  \pgfmathsetmacro{\they}{\pgfmathresult}
  \draw[->] (\thex,\prevy) -- (\thex,\they);
  %\draw(\thex,\prevy) -- (\thex+5,\they);
\end{tikzpicture}
\end{document}

So the elements to animate are Circle[open] and whether to display the t=... label.

2
  • 3
    If you show us the unanimated version with tikz, I'm sure we can then help you to do the animation Mar 3, 2023 at 11:50
  • You can just do \pgfmathsetmacro\mymacro{<my formula>}. \pgfmathsetmacro is also doing \pgfmathparse and stores the result in \mymacro. Mar 3, 2023 at 19:33

3 Answers 3

3

I believe you got your answer, i.e. use layers with TikZ, and both answers show how one can do this.

I want to show a different way to draw this timeline by using a few goodies, TikZ has to offer, mainly the /tikz/y key where you can change the length and the direction of the y axis of the xyz coordinate system (the one without units).

Instead of using \axscale you can just set y to -0.02cm (where the default is 1cm) and TikZ multiplicates your value to transform it into the canvas coordinate system (the one with units where y still points upwards).

Then, there's the chains library which I'm actually only using to join nodes by not having it go anywhere. For this I setup a start point that is 1mm above t = 0 and also add a last point that is always 1.4mm below the last t. (If you need the upper start of the line to be a fixed distance above the first t an adjustment is necessary here.) The last one is also joined by -> so that we get an the actual arrow tip.

Speaking of arrow tips, while the Circle tip seems like a nice thing, they only touch the specified coordinate instead of lying centered on them. This can be fixed, though I'd just use circle nodes here.

For making the diagram beamer aware, I'm stealing the <.> syntax from Sam Carter's answer to have the label show up at the same time as the filling of the node. Since I'm using a circle node as reference instead of an arrow tip, the node will line up much better in my opinion.

We could also add the label to the fill, i.e.

alt=<+>{fill, label={$t = \t$}}{}

though this will make the picture jump around unless the label wouldn't contribute to the bounding box anymore.
Since the visible on solution from overlay-beamer-styles will leave hidden text on the frame (which can get selected and copied), I'm using beamer's own \uncover to hide the text.

Code

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, chains, overlay-beamer-styles}
\begin{document}
\begin{frame}
\begin{itemize}[<+->]
\item First.
\item Second.
\end{itemize}

\begin{tikzpicture}[
  y=-.02cm, thick, label position=right, start chain = going {},
  dot/.style={circle, draw, inner sep=+0pt, minimum size=+1.3mm}]
\coordinate[on chain]() at (0, 1mm); % a start (for the line)
\foreach \t in {2, 12, 22, 32, 44, 76, 116, 182, 300}
  \node[dot, on chain, join, alt=<+>{fill},
    label/.expanded={$\uncover<.>{t = \t}$}, % no hidden text in output
%    label={[visible on=<.>]$t = \t$},       % hidden text in output
  ] at (0, \t) {};
% and an end that is below the last dot
\coordinate[on chain, join=by ->]() at ([yshift=-1.4mm] chain-end.south);
\end{tikzpicture}
\end{frame}
\end{document}

Output (click for full version)

Thumbnail to full file

1
  • So much more compact than my code! I was quite sure it was possible, but since there were requests to close my question before I offered my clumsy own work, I felt I had to go thru that and then bias the answer towards just a patch of my code.
    – Joce
    Mar 5, 2023 at 10:55
4

You can make use of the fact that tikz commands, like \draw, are overlay aware:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

\begin{document}
\begin{frame}
\begin{tikzpicture}
  \def\axscale{-0.02}
  \def\thex{0}
  \def\they{0}
  \def\prevy{0}
  \def\times{{-5,2, 12, 22, 32, 44, 76, 116, 182, 300,307}}
  \def\maxt{9}
  \foreach \it in {1,...,\maxt} {
        \pgfmathparse{\axscale*\times[\it-1]}
        \pgfmathsetmacro{\prevy}{\pgfmathresult}
        \pgfmathparse{\axscale*\times[\it]}
        \pgfmathsetmacro{\they}{\pgfmathresult}
        \draw[-{Circle[open]}] (\thex,\prevy) -- (\thex,\they);
        \draw<+(2)>[-{Circle}] (\thex,\prevy) -- (\thex,\they);
        \node<.(2)>[right,anchor=west] at (\thex,\they) {
            $t=\pgfmathparse{\times[\it]}
            \pgfmathprintnumber[    % Print the result
                fixed,
                fixed zerofill,
                precision=0,
                assume math mode=true
            ]{\pgfmathresult}
            $};
  }
  \pgfmathparse{\axscale*\times[\maxt]}
  \pgfmathsetmacro{\prevy}{\pgfmathresult}
  \pgfmathparse{\axscale*\times[\maxt+1]}
  \pgfmathsetmacro{\they}{\pgfmathresult}
  \draw[->] (\thex,\prevy) -- (\thex,\they);
  %\draw(\thex,\prevy) -- (\thex+5,\they);
\end{tikzpicture}
\end{frame}
\end{document}

enter image description here

3
  • Thanks a lot, I didn't know of <+>. Since there are 2 overlays before I start using that time line, I have found that <+(2)> was the appropriate choice, and I've actually grouped the draw and node commands in an only<+(2)> one since I want the times too to show only on the corresponding slide.
    – Joce
    Mar 3, 2023 at 19:02
  • 1
    @JoceNoToPutinsWarInUkraine You can use \node<.(2)> to show the node only on the same overlay as the filled circle. However if you are only showing the times one at a time, I would use the visible on option from the overlay-beamer-styles library @Jasper Habicht uses in his answer. This avoid the slight height difference from showing the first/last node which causes a bit of jump between the slides. Mar 3, 2023 at 19:11
  • +1. I have actually lengthened the arrow above first and below last time point for other reasons, so I don't have this jump. But that's usefule to note, as well as the <.> syntax.
    – Joce
    Mar 3, 2023 at 19:14
3

Using the great overlay-beamer-styles library, you can do:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{overlay-beamer-styles}

\begin{document}
\begin{frame}

\begin{tikzpicture}
  \def\axscale{-0.02}
  \def\thex{0}
  \def\they{0}
  \def\prevy{0}
  \def\times{{-5, 2, 12, 22, 32, 44, 76, 116, 182, 300, 307}}
  \def\maxt{9}
  \foreach \it in {1,...,\maxt} {
        \pgfmathparse{\axscale*\times[\it-1]}
        \pgfmathsetmacro{\prevy}{\pgfmathresult}
        \pgfmathparse{\axscale*\times[\it]}
        \pgfmathsetmacro{\they}{\pgfmathresult}
        \draw[alt={<\it>{-{Circle[]}}{-{Circle[open]}}}] (\thex,\prevy) -- (\thex,\they);
        \node[right,anchor=west] at (\thex,\they) {
            $t=\pgfmathparse{\times[\it]}
            \pgfmathprintnumber[    % Print the result
                fixed,
                fixed zerofill,
                precision=0,
                assume math mode=true
            ]{\pgfmathresult}
            $};
  \pgfmathparse{\axscale*\times[\maxt]}
  \pgfmathsetmacro{\prevy}{\pgfmathresult}
  \pgfmathparse{\axscale*\times[\maxt+1]}
  \pgfmathsetmacro{\they}{\pgfmathresult}
  \draw[->] (\thex,\prevy) -- (\thex,\they);
  }
  %\draw(\thex,\prevy) -- (\thex+5,\they);
\end{tikzpicture}

\end{frame}
\end{document}

enter image description here

Or you can replace alt={<\it>{-{Circle[]}}{-{Circle[open]}}} with alt={<\it->{-{Circle[]}}{-{Circle[open]}}} (that is, add a - after \it) if you want to keep the previous dots filled.

You must log in to answer this question.

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