# Splitting a beamer animation

I have a complex animation that evolves over a series of slides (a \foreach \frm in {1,...,12}\only<\frm>{ loop where certain parts are selected on individual slides with \visible).

So far I had all overlays inside a single frame, but I would like to distribute it to several frames so I can put other frames (with text and other things) in between, so I moved the entire tikzpicture where all overlays are created into a \newcommand{\makeAnimation}[1] such that I can say, e.g.

\begin{frame}{First part of the animation}
\makeAnimation{1,...,4}
\end{frame}

\begin{frame}{Some explanations}
Lorem ipsum
\end{frame}

\begin{frame}{Next part}
\makeAnimation{4,...,7}
\end{frame}


(It is easier to create the whole thing in one go, because I would have to copy a lot of code otherwise)

However, the after the portion of the animation that is (correctly) generated by \makeAnimation{1,...,4} I get an extra empty slide, which I am unable to move away. Worse, if I change the \only after the \foreach statement, into a \visible (this keeps the centered tikzpicture from jumping around) it generates all slides from 1 ... 12 but leaves 5 ... 12 blank.

How can I fix this and get rid of the extra slides? At this point I would accept any hack as long as I don't have to split up/redo the animation.

Small example:

\documentclass[
presentation,
english,
]{beamer}
%\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{tikz}

\newcommand{\makeAnimation}[1]{
\begin{center}
\scalebox{0.7} {
\begin{tikzpicture}
\foreach \frm in {#1} {
\only<\frm>{
\node {FRAME \frm};
\visible<3>{\node at (4,0) {three hippos};}
\visible<4-5>{\node (a) at (2,0) {a couple giraffes};}
\visible<5-6>{\node (b) at (4,2) {hello};}
\visible<5>{\path[-] (a) edge (b);}
\visible<6>{\node at (4,0) {six elephants};}
}
}
\end{tikzpicture}
}
\end{center}
}

\begin{document}
\begin{frame}{foo}
\makeAnimation{1,...,4}
\end{frame}
\begin{frame}{bar}
next slide
\end{frame}
\end{document}


Produces

foo FRAME 1
foo FRAME 2
foo FRAME 3 three hippos
foo FRAME 4 a couple giraffes
foo                  % evil blank slide
bar next slide

-
I think this would be a lot easier to diagnose if you added a minimal working example. You have some code now, but I would be interested in the definition of \makeanimation for instance. Best would be to just add a complete minimal working example showing the problem. – Roelof Spijker Mar 1 '12 at 10:52
@RoelofSpijker: I added a small (close to minimal) example to demonstrate the issue. Note that changing only to visible will produce two blank slides. – bitmask Mar 1 '12 at 11:10
I have changed the title from "Overlays generate empty slide at the end" to "Splitting a beamer animation", since I think that's the larger question you were asking and, perhaps, it will now be easier to find in a search. – Ryan Reich Mar 1 '12 at 18:56
@RyanReich: +1 on that. – bitmask Mar 1 '12 at 19:17

If I may be so bold, I want to say that you are doing it wrong. beamer has a built-in way of "cutting" frames: the \againframe command, combined with overlay specifications on the frame to be cut. It's described in the manual, section 11.2 ("Repeating a frame at a later point"), and works like this:

\documentclass[
presentation,
english,
]{beamer}
%\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{tikz}

\begin{document}

\begin{frame}<1-4>[label = foo]{foo}
\begin{tikzpicture}
\onslide<1>
\node {Frame 1};
\onslide<2>
\node {Frame 2};
\onslide<3>
\node at (4,0) {three hippos};
\onslide<4-5>
\node (a) at (2,0) {a couple giraffes};
\onslide<5-6>
\node (b) at (4,2) {hello};
\onslide<5>
\path[-] (a) edge (b);
\onslide<6>
\node at (4,0) {six elephants};
\end{tikzpicture}
\end{frame}

\begin{frame}{bar}
next slide
\end{frame}

\againframe<4-6>{foo}
\end{document}


Basically, the first frame is the "template" for the animation and replaces your \makeAnimation. The overlay specification says only to run it for four slides, and then cut to the explanation. Then \againframe comes in and produces slides 4 through 7 to finish the animation.

I am a little annoyed that it is necessary to write Frame 1 and Frame 2 separately, as there does exist a counter framenumber that should print the correct value in a single \theframenumber command. However, when I tried

\onslide<1-2>


it just printed "Frame 1" twice. Using \only<1-2> did the same, and in fact, using Frame \theframenumber with two \onslide commands also printed "Frame 1" even after \onslide<2>! Perhaps this is a bug; certainly, this counter is not mentioned in the manual, so perhaps it is not supported.

-
I ... don't have words. This is exactly what I wanted to have. I've been messing around with increasingly ugly (seriously, you wouldn't believe it) hacks to get this right. Just wow! Thank you! – bitmask Mar 1 '12 at 18:37

Avoid unnecessary \visible<...> lines, let it depend on your argument range. After I removed the \visible<5> and \visible<6> lines in your example, the empty frame was gone.

The code (before the question has been updated) could even be reduced, doing the same but no empty slide:

\begin{tikzpicture}
\foreach \frm in {#1} {
\only<\frm>{
\node {FRAME \frm};
\visible<\frm>{\node at (4,0) {its \frm};}
}
}
\end{tikzpicture}


Even with the update, you could use \if or similar or a \foreach loop for \visible and a variable for the node content.

If it's just for preventing jumping, I would use \overlayarea.

-
Sure, but that completely misses the point of the complete animation. – bitmask Mar 1 '12 at 12:05
Sorry, but it's not. Perhaps the example was a bit too simple, but in general there are interleaving visibility scopes where the content is not derived that easily from the value of \frm. Let me update the question. – bitmask Mar 1 '12 at 12:16
I tried wrapping \visible in an \ifthenelse statement. But with the exact same effect. I didn't manage to get it working with \if. – bitmask Mar 1 '12 at 12:54

I found that it is best to play dirty with tex. This does the trick, as it wraps the entire thing.

% parameter documentation
%  #1: current frame
%  #2: displayed range minimum
%  #3: displayed range maximum
%  #4: object range minimum
%  #5: object range maximum
%  #6: object
\newcommand{\showPart}[6]{\ifnum#1<#4\relax\else\ifnum#5<#1\relax\else\visible<\ifnum#2<#4 #4\else#2\fi-\ifnum#3<#5 #3\else#5\fi>{#6}\fi\fi}


Which allows the animation command to look like that:

\begin{tikzpicture}
\foreach \frm in {#1,...,#2} {
%\only<\frm>{  %%%%% IMPORTANT: remove this!
\node at (-4,\frm) {FRAME \frm}; %% all four shown all the time!
\showPart{\frm}{#1}{#2}{2}{4}{\node at (4,0) {it's 2-4};}
\showPart{\frm}{#1}{#2}{4}{5}{\node at (4,2) {it's 4-5};}
\showPart{\frm}{#1}{#2}{5}{5}{\node at (4,4) {it's 5};}
%}
}
\end{tikzpicture}

-
On the contrary, I have found that it is best to be stodgily bureaucratic with LaTeX and to do it "by the book" whenever possible. A package like beamer, which has quite a large book indeed, should be expected to anticipate this kind of need. – Ryan Reich Mar 1 '12 at 18:17