[Tex/LaTex] reference overlay numbers with names

beameroverlays

I have two-column slides where there is a tikz figure on the left, and itemization on the right. There is >10 overlays due to pauses in the itemization, and some pieces of the tikz picture are added/removed/modified accordingly (with \only<>) as are the items uncovered.

It is easy to break the code by adding one \pause, because all numbers have to be rewritten.

Is there a way (no hint in Beamer Manual, chap. 9) to assign the value of beamerpause counter to symbolic names, at the point when that part gets uncovered for the first time, something like (needs multiple passes to be resolved) the following?

\begin{column}{..}
   \only</bar->{...}  % <2-> (use e.g. / to reference labels)
   \only<-/baz>{...}  % <-3>
\end{column}
\begin{column{..}
   \begin{itemize}
      \item foo \pause
      \item bar \firstUncoveredLabel{bar}\pause % assign 2 to label /bar
      \item baz \pause[baz]       % nicer syntax; assign 3 to label /baz
      \item end
   \end{itemize}
\end{column}

EDIT: minimal working example:

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
   \begin{frame}
      \begin{columns}
         \begin{column}{.5\textwidth}
            \tikz{
               \draw< -3>        (0,0) grid (3,3);
               \draw<2-3>[red]   (0,0) -- (3,1);
               \draw<3- >[green] (0,0) -- (3,2);
               \draw<4  >[blue]  (0,0) -- (3,3);
            }
         \end{column}
         \begin{column}{.5\textwidth}
            \begin{itemize}
               %%%% uncomment this item and all numbers above have to be shifted :-(
               % \item important remark at the beginning \pause 
               \item grid \pause
               \item grid, red \pause
               \item grid, red, green \pause
               \item green, blue
            \end{itemize}
         \end{column}
      \end{columns}
   \end{frame}
\end{document}

and this is what I dream of (does not compile):

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
   \begin{frame}
      \begin{columns}
         \begin{column}{.5\textwidth}
            \tikz{
               %% use symbolic names for overlay specificaiton
               \draw<-/gridRedGreen>                (0,0) grid (3,3);
               \draw</gridRed-/gridRedGreen>[red]   (0,0) -- (3,1);
               \draw</gridRedGreen->        [green] (0,0) -- (3,2);
               \draw</last>                 [blue]  (0,0) -- (3,3);
            }
         \end{column}
         \begin{column}{.5\textwidth}
            \begin{itemize}
               %%%% uncomment and overlays are still correct :-)
               % \item important remark at the beginning \pause 
               \item grid                \pause[grid]
               \item grid, red           \pause[gridRed]
               \item grid, red, green    \pause[gridRedGreen]
               \item green, blue      
            \end{itemize}
         \end{column}
      \end{columns}
   \end{frame}
\end{document}

Best Answer

Here's a possible way to reference overlays by name:

\makeatletter
\DeclareRobustCommand*{\savepause}[1]{\only<1>{\immediate\write\@auxout{\string\pauseentry{\the\c@framenumber}{#1}{\the\c@beamerpauses}}}}
\newcommand*{\usepause}[1]{\@ifundefined{pauses@\the\c@framenumber @#1}{1}{\@nameuse{pauses@\the\c@framenumber @#1}}}
\newcommand*{\pauseentry}[3]{\global\@namedef{pauses@#1@#2}{#3}}
\makeatother

Include this code somewhere into the preamble of your document, i. e. between \documentclass{beamer} and \begin{document}. It defines two userlevel commands, \savepause and \usepause:

  • \savepause{overlayname} saves the current value of the counter beamerpauses as overlayname. Issue it immediatly before the \pause command.
  • \usepause{overlayname} refers to the previously saved value of overlayname, so if you e.g. used \savepause{overlayname} on the third overlay, \usepause{overlayname} will expand to 3.

As the values will be saved to the auxiliary file, this needs at least two LaTeX runs to produce a stable output.

You can't use the syntax \pause[overlayname] to save the value as you suggested because the optional argument is already used by beamer itself. However, you can define your own command for convenience:

\newcommand*{\mypause}[1]{\savepause{#1}\pause}

which would be used like \mypause{overlayname}.

Example code:

\documentclass{beamer}
\makeatletter
\DeclareRobustCommand*{\savepause}[1]{\only<1>{\immediate\write\@auxout{\string\pauseentry{\the\c@framenumber}{#1}{\the\c@beamerpauses}}}}
\newcommand*{\pauseentry}[3]{\global\@namedef{pauses@#1@#2}{#3}}
\newcommand*{\usepause}[1]{\@ifundefined{pauses@\the\c@framenumber @#1}{1}{\@nameuse{pauses@\the\c@framenumber @#1}}}
\makeatother
\usepackage{tikz}
\begin{document}
   \begin{frame}
      \begin{columns}
         \begin{column}{.5\textwidth}
            \tikz{
               %% use symbolic names for overlay specificaiton
               \draw<-\usepause{gridRedGreen}>                (0,0) grid (3,3);
               \draw<\usepause{gridRed}-\usepause{gridRedGreen}>[red]   (0,0) -- (3,1);
               \draw<\usepause{gridRedGreen}->        [green] (0,0) -- (3,2);
               \draw<\usepause{last}>                 [blue]  (0,0) -- (3,3);
            }
         \end{column}
         \begin{column}{.5\textwidth}
            \begin{itemize}
               %%%% uncommented and overlays are still correct :-)
               \item important remark at the beginning \pause 
               \item grid                \savepause{grid}\pause
               \item grid, red           \savepause{gridRed}\pause
               \item grid, red, green    \savepause{gridRedGreen}\pause
               \item green, blue      
            \end{itemize}
         \end{column}
      \end{columns}
  \savepause{last} 
  \end{frame}
\end{document}

Output after two LaTeX runs (click on the image to see it full size):

output of the example code (five frames)

Related Question