animateinline
我正在编写一个 Beamer 演示文稿,其中包含一个通过包内的环境创建的动画animate
。当我创建幻灯片的讲义(通过设置选项handout
)时,我希望将动画的每一帧显示为单独的幻灯片,最好不显示动画控件。有没有一种简单的方法可以做到这一点,而不需要重复动画代码?
显示我想要实现的目标的一个简单的例子是:
\documentclass{beamer}
\usepackage{animate}
\usepackage{boolexpr}
\begin{document}
\begin{frame}
\begin{center}
\begin{animateinline}[controls]{1}
\multiframe{2}{iStep=1+1}
{
\ifthenelse{\iStep=1}{Frame 1}{Frame 2}
}
\end{animateinline}
\end{center}
\end{frame}
\end{document}
这会产生一个包含两个帧的动画。我想要的是,当我将源更改为包含文档类handout
的选项beamer
时,动画的每个帧都对应讲义中的一张新幻灯片(因此讲义将有两张幻灯片)。
答案1
这将禁用animateinline
环境,并修改\multiframe
循环,以便它
\only<2|handout:2>{.....}
使用循环计数器,<...>
因此 beamer 可以执行其正常操作,并制作与迭代的每一帧相对应的幻灯片。(仅XXX
修改了标记的两行。)
需要规范handout
来强制其在讲义模式下使用多张幻灯片。
\documentclass
%[handout]
{beamer}
\usepackage{animate}
\usepackage{boolexpr}
\makeatletter
\def\animateinline[#1]#2{%
\@anim@insidetrue
}
\def\endanimateinline{}
\renewcommand{\multiframe}[3]{% #1: #repetitions, #2: vars, #3: frame content
\unskip%
\if@anim@inside\else%
\PackageError{animate}{%
\protect\multiframe\space cannot be used outside `animateinline'%
\MessageBreak environment%
}{}%
\fi%
\if@anim@insidemulti%
\PackageError{animate}{\protect\multiframe\space cannot be nested}{}%
\fi%
\setboolean{@anim@insidemulti}{true}%
%reset macro for updating variables
\gdef\@anim@updatevars{}%
%reset loop counter
\global\@anim@mulframecnt=\z@%
%remove spaces from variable declaration list (2nd arg)
\xdef\@anim@vardecls{#2\space}%
\xdef\@anim@vardecls{\expandafter\zap@space\@anim@vardecls\@empty}%
\ifnum#1<\z@%
\PackageError{animate}{%
\protect\multiframe: first argument must be greater than zero%
}{}%
\fi%
%parse list of variable declarations and build macro for updating them
\expandafter\@anim@parsevars\@anim@vardecls,\@nil%
\whiledo{\@anim@mulframecnt<#1}{%
\ifnum\@anim@mulframecnt>\z@%
% \newframe% don't do this XXX
\@anim@updatevars% update variables
\fi%
\global\advance\@anim@mulframecnt by \@ne%
\ignorespaces%
\only<\the\@anim@mulframecnt|handout:\the\@anim@mulframecnt>{#3}% execute loop body( using \only<>) XXX
\unskip%
}%
\setboolean{@anim@insidemulti}{false}%
\ignorespaces%
}
\makeatother
\begin{document}
\begin{frame}
\begin{center}
\begin{animateinline}[controls]{1}
\multiframe{2}{iStep=1+1}
{
\ifthenelse{\iStep=1}{Frame 1}{Frame 2}
}
\end{animateinline}
\end{center}
\end{frame}
\end{document}
答案2
这是一个更普遍使用的解决方案(来自内部人员),因为它适用于嵌入式\newframe
s、缩放选项\animategraphics
、时间线等......
animate
仅当类选项 optionhandout
实际设置后,才会修补内部宏(感谢\@ifclasswith{beamer}{handout}{.... }{}
David Carlisle):
\documentclass
[handout]
{beamer}
\usepackage{animate}
\makeatletter
\newcount\@currentframe
\@ifclasswith{beamer}{handout}{
%non-interactive Widget annotation, representing one frame of the animation
\ifpdf
\def\@anim@makeframe#1#2{% #1:@anim@num, #2:@anim@curframe@zb
%container XObject for all transparencies that compose the frame
\begingroup%
\setlength{\unitlength}{1pt}%
\global\setbox\@anim@box=\hbox{%
\pdfliteral{q}%
\begin{picture}(\@anim@framewidth,\@anim@frametotalheight)%
\end{picture}%
\pdfliteral{Q\@anim@getkeyval{frmcontent@#2}}%
}%
\endgroup%
\immediate\pdfxform resources {%
/XObject <<\@anim@getkeyval{frmxobject@#2}>>}\@anim@box%
\if@anim@useocg%
\@anim@newocg{#1}{#2}%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{}{%
\xdef\@anim@offocgs{\@anim@offocgs\space\@anim@curocg}%
}%
\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posternone%
\xdef\@anim@offocgs{\@anim@offocgs\space\@anim@curocg}%
\fi%
\else%
\xdef\@anim@offocgs{\@anim@offocgs\space\@anim@curocg}%
\fi%
\fi%
\def\@anim@annotflag{/F 4}%, print, visibility set by OCG
\else%
%widget visibility state
\def\@anim@annotflag{/F 4}%, print, visibility set by OCG
\ifx\@anim@poster\@anim@posternone\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posterfirst%
\def\@anim@annotflag{/F 4}% visible, print
\fi%
\fi%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{%
\def\@anim@annotflag{/F 4}%
}{}%
\fi%
\fi%
\fi%
%frame widget, using the container XObject as its Appearance
\pdfannot
width \@anim@animwidth\p@ height \@anim@animheight\p@
depth \@anim@animdepth\p@
{%
/Subtype/Widget%
\@anim@annotflag
\if@anim@useocg%
/OC \@anim@curocg %associate widget with the just created OCG
\fi%
/FT/Btn/Ff 65537% non-interactive push button
/BS <</W 0>>%
/AP <</N \the\pdflastxform\space 0 R>>%
/T (#1.#2)%
}%
%\xdef\@anim@fields{\@anim@fields\space\the\pdflastannot\space 0 R}%
}
\else
\if@anim@@dvipdfmx
\def\@anim@makeframe#1#2{%
%container XObject
\global\setbox\@anim@box=\hbox{%
\special{pdf:content \@anim@getkeyval{frmcontent@#2}}%
}%
\special{pdf:bxobj @anim@anmfrm@#1@#2 width \@anim@framewidth pt
height \@anim@frameheight pt depth \@anim@framedepth pt}%
\begin{picture}(0,0)\put(0,0){\box\@anim@box}\end{picture}%
\special{pdf:put @resources <<
/XObject <<\@anim@getkeyval{frmxobject@#2}>>%
>>}%
\special{pdf:exobj}%
\if@anim@useocg%
\@anim@newocg{#1}{#2}%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{}{%
\special{pdf:put @anim@offocgs @anim@ocg@#1@#2}%
}%
\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posternone%
\special{pdf:put @anim@offocgs @anim@ocg@#1@#2}%
\fi%
\else%
\special{pdf:put @anim@offocgs @anim@ocg@#1@#2}%
\fi%
\fi%
\def\@anim@annotflag{/F 4}%
\else%
\def\@anim@annotflag{/F 4}%
\ifx\@anim@poster\@anim@posternone\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posterfirst%
\def\@anim@annotflag{/F 4}%
\fi%
\fi%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{%
\def\@anim@annotflag{/F 4}%
}{}%
\fi%
\fi%
\fi%
%frame widget
\special{pdf:annot @annot@\the\@anim@fieldnum\space
width \@anim@animwidth pt height \@anim@animheight pt
depth \@anim@animdepth pt <<%
/Subtype/Widget%
\@anim@annotflag
\if@anim@useocg/OC @anim@ocg@#1@#2\fi%
/FT/Btn/Ff 65537%
/BS <</W 0>>%
/AP <</N @anim@anmfrm@#1@#2>>%
/T (#1.#2)%
>>%
}%
%\special{pdf:put @anim@fields @annot@\the\@anim@fieldnum}%
\global\advance\@anim@fieldnum by \@ne%
}
\else
\def\@anim@makeframe#1#2{%
%container XObject
\special{ps:
mark /_objdef {@anim@anmfrm@#1@#2} /type/stream /OBJ pdfmark
mark {@anim@anmfrm@#1@#2} (\@anim@getkeyval{frmcontent@#2}) /PUT
pdfmark
mark {@anim@anmfrm@#1@#2} <<
/Type/XObject/Subtype/Form/FormType 1
/BBox [frame@llx frame@lly frame@urx frame@ury]
/Resources <</XObject <<\@anim@getkeyval{frmxobject@#2}>>>>
>> /PUT pdfmark
}%
\if@anim@useocg%
\@anim@newocg{#1}{#2}%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{}{%
\special{ps: mark {@anim@offocgs} {@anim@ocg@#1@#2} /APPEND pdfmark}%
}%
\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posternone%
\special{ps: mark {@anim@offocgs} {@anim@ocg@#1@#2} /APPEND pdfmark}%
\fi%
\else%
\special{ps: mark {@anim@offocgs} {@anim@ocg@#1@#2} /APPEND pdfmark}%
\fi%
\fi%
\def\@anim@annotflag{/F 4}%
\else%
\def\@anim@annotflag{/F 4}%
\ifx\@anim@poster\@anim@posternone\else%
\ifnum#2=\z@%
\ifx\@anim@poster\@anim@posterfirst%
\def\@anim@annotflag{/F 4}%
\fi%
\fi%
\ifx\@anim@poster\@anim@posterlast%
\@anim@keytoaux{a#1.poster}{#2}%
\ifthenelse{\equal{\@anim@getkeyval{a#1.poster}}{#2}}{%
\def\@anim@annotflag{/F 4}%
}{}%
\fi%
\fi%
\fi%
%frame widget
\begingroup%
\setlength{\unitlength}{1pt}%
\begin{picture}(0,0)% mark annotation rectangle
\put(0,-\@anim@animdepth){%
\special{ps:
currentpoint /wid@lly exch def /wid@llx exch def
}%
}%
\put(\@anim@animwidth,\@anim@animheight){%
\special{ps:
currentpoint /wid@ury exch def /wid@urx exch def
}%
}%
\end{picture}%
\endgroup%
\special{ps:
mark
/_objdef {annot@\the\@anim@fieldnum}%
/Rect [wid@llx wid@lly wid@urx wid@ury]%
/Subtype/Widget%
\@anim@annotflag
\if@anim@useocg/OC {@anim@ocg@#1@#2}\fi%
/FT/Btn/Ff 65537
/BS <</W 0>>%
/AP <</N {@anim@anmfrm@#1@#2}>>%
/T (#1.#2)%
/ANN pdfmark
%mark {\@anim@fields} {annot@\the\@anim@fieldnum} /APPEND pdfmark
}%
\global\advance\@anim@fieldnum by \@ne%
}
\fi
\fi
\let\@anim@makeframe@orig\@anim@makeframe
\def\@anim@makeframe#1#2{% #1:@anim@num, #2:@anim@curframe@zb
\@currentframe=#2\relax%
\advance\@currentframe by \@ne%
\only<\@currentframe|handout:\@currentframe>{\@anim@makeframe@orig{#1}{#2}}%
}
\def\@anim@animwidget#1{%
\hbox to \@anim@animwidth\p@ {%
\vrule width 0pt height \@anim@animheight\p@ depth \@anim@animdepth\p@%
\hss%
}%
}%
\def\@anim@insertwidgets#1#2{%#1:@anim@num, #2 existing btn colour combination
\vtop{%
\offinterlineskip%
\hbox{\@anim@animwidget{#1}}%
\if@anim@controls%
\setlength{\@anim@tmpdima}{\@anim@btnsize}%
\vskip 0.1\@anim@tmpdima%
\hbox to \@anim@animwidth\p@ {%
\hss\vrule width 0pt height \@anim@tmpdima depth 0pt\hss%
}%
\fi%
}%
}
}{}
\makeatother
\begin{document}
\begin{frame}
\begin{center}
\begin{animateinline}[controls,scale=2]{1}
Frame 1
\newframe
Frame 2
\newframe
\multiframe{2}{iStep=3+1}{Frame \iStep}
\newframe
Frame 5
\end{animateinline}
\end{center}
\end{frame}
\end{document}