我希望在后面的帧中重新出现一个特定的图形,以便我可以更多地谈论它,最好保留原始的图形计数器数字。在这两种情况下,都会有一些文本或其他内容伴随图形。
这个问题类似于这,这,或这个。第一个链接中的解决方案似乎过于手动,第二个看起来不错,但我无法将其编译到 beamer 文档中,第三个仅涉及图形计数器的问题。我尝试使用环境lrbox
来保存图形的内容,但这似乎也不起作用:
\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\newsavebox{\myfigurebox}
\begin{document}
\begin{frame}{First Frame}
\begin{lrbox}{\myfigurebox}
\begin{tikzpicture}
\draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
\end{tikzpicture}
\end{lrbox}
\begin{figure}
\centering
\usebox{\myfigurebox}
\caption{Description.}
\end{figure}
Some text.
\end{frame}
\begin{frame}{Other Frame}
\begin{figure}
\centering
\usebox{\myfigurebox}
\caption{Description (again).}
\end{figure}
More text.
\end{frame}
\end{document}
还尝试了其他变化,例如用 包围figure
环境lrbox
、移到lrbox
外面frame
等等,但这些也没有起作用。
现在,我唯一接近的解决方案是使用覆盖规范和\againframe
,但这会弄乱方程式数字或其他计数器。
\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\begin{document}
\begin{frame}<1>[label=myframe]
\frametitle<1>{First Frame}
\frametitle<2>{Other Frame}
\begin{figure}
\centering
\begin{tikzpicture}
\draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
\end{tikzpicture}
\caption{Description.}
\end{figure}
\begin{overprint}
\onslide<1>
Some text.
\onslide<2>
More text. % imagine there are some equations or other counters here; the equation numbering would be wrong
\end{overprint}
\end{frame}
% later...
\againframe<2>{myframe}
\end{document}
如果同一个数字重复很多次,这种“黑客”方式可能会失控……
答案1
\begin{lrbox}
在 a 中拥有etcframe
使它成为 的局部frame
,因此以后无法调用它,除非定义一个globallrbox
环境并使用它。这样的定义可以通过\usepackage{etoolbox} \usepackage{letltxmacro} \LetLtxMacro{\globallrbox}{\lrbox} \LetLtxMacro{\endgloballrbox}{\endlrbox} \patchcmd{\globallrbox}{\setbox}{\global\setbox}{}{\showtokens{patching globallrbox failed}}
图形编号会有所不同,因为
\caption
命令负责分配编号,而您有两个\caption
命令。尝试将整个figure
环境放在一个框中可能并不容易(而且您也不能caption
在没有环境的情况下将 放在框中figure
),并且不允许您第二次将文本“(再次)”附加到标题,所以最好摆弄标签/计数器,就像我下面所做的那样,扩展示例以显示在中间放置其他图形的效果。
在下文中,我避免使用环境,并将框架globallrbox
移到外部,以便更好地说明各种方法。您可以通过提供用于保存和调用图形的附加宏/环境来进一步整理它。lrbox
\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\newsavebox{\myfigurebox}
\makeatletter
\newcommand*{\localsetcounter}[2]{% same as LaTeX's \setcounter, but removed the \global
\@ifundefined {c@#1}{\@nocounterr {#1}}%
{\csname c@#1\endcsname #2\relax}%
}
\newcommand*{\reusefigurecounter}[1]{%only use this within your figure environment to keep the changes local to that environment, and before the \caption command!
\localsetcounter{figure}{\getrefnumber{#1}}%
\let\refstepcounter\@gobble
}
\makeatother
\setcounter{errorcontextlines}{\maxdimen}
\begin{document}
\begin{lrbox}{\myfigurebox}% the lrbox is outside any frames, but after \begin{document} so that the right fonts and things are set up, and before we first want to use it
\centering
\begin{tikzpicture}
\draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
\end{tikzpicture}
\end{lrbox}
\begin{frame}{First Frame}
\begin{figure}
\usebox{\myfigurebox}
\caption{Description.}
\label{myfigure}
\end{figure}
Some text.
\end{frame}
\begin{frame}{Another Frame}
\begin{figure}
something else
\caption{Description.}
\end{figure}
Some text.
\end{frame}
\begin{frame}{Other Frame}
\begin{figure}
\centering
\usebox{\myfigurebox}
\reusefigurecounter{myfigure}
\caption{Description (again).}
\end{figure}
More text.
\end{frame}
\begin{frame}{Another Frame}
\begin{figure}
something else entirely
\caption{Description.}
\end{figure}
Some text.
\end{frame}
\end{document}
更新:界面稍微好一点?
使用此版本,savefigure
在您希望显示该图形的第一个副本之前的任何位置使用环境,在第一个参数中提供一个标签,以便稍后调用它。然后使用\figurefirstuse
或\reusefigure
命令调用或调用该图形,具体取决于它是否已经显示。这些命令的参数是标签名称和标题,对于同一图像的所有调用,它们不必相同。它目前不会自动保存任何以前使用的标题。
不确定这些东西是否必要或优雅,但似乎有效,现在也有覆盖层。请注意,至少在错误处理方面存在一些限制。很难自动确定图形是否是第一次使用,因为在重新处理多张幻灯片的帧(即覆盖和暂停)时beamer
会重置figure
计数器,因此我暂时放弃尝试这样做。
还有一个figureandsave
环境,它保存图形并在同一位置显示它,内部调用上述命令。\figurefirstuse
在这种情况下采用与相同的参数。
我保留了上面的旧版本,因为这样可能更清楚实际发生了什么。希望下面的示例比我的描述能更好地说明新界面。
\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\makeatletter
\newcommand*{\localsetcounter}[2]{% same as LaTeX's \setcounter, but removed the \global
\@ifundefined {c@#1}{\@nocounterr {#1}}%
{\csname c@#1\endcsname #2\relax}%
}
\newcommand*{\reusefigurecounter}[1]{%#1=label, only use this within your figure environment to keep the changes local to that environment, and before the \caption command!
\localsetcounter{figure}{\getrefnumber{#1}}%
\let\refstepcounter\@gobble
}
\usepackage{etoolbox}
\usepackage{letltxmacro}
\LetLtxMacro{\globallrbox}{\lrbox}
\LetLtxMacro{\endgloballrbox}{\endlrbox}
\patchcmd{\globallrbox}{\setbox}{\global\setbox}{}{\showtokens{patching globallrbox failed}}
\newenvironment{figureandsave}[2]{% parameters #1=label name,#2=caption
\def\currsavefigurecaption{#2}%
\def\currsavefigurename{#1}%
\begin{savefigure}{#1}}%
{\end{savefigure}%
\figurefirstuse{\currsavefigurename}{\currsavefigurecaption}%
}
% can use savefigure within or outside of a frame, but always after \begin{document}
\newenvironment*{savefigure}[1]{% parameters #1=label name
\expandafter\newbox\expandafter{\csname savedfigure#1box\endcsname}%use \newbox instead of \newsavebox as we have to allow beamer to process the same figure multiple times if a frame contains multiple slides
\begin{globallrbox}{\csname savedfigure#1box\endcsname}%
}
{\end{globallrbox}}
% use \figurefirstuse the first time you want to show the figure
\newcommand\figurefirstuse[2]{% parameters #1=label name,#2=caption
\@ifundefined{savedfigure#1box}{\errmessage{figure #1 hasn't been saved yet}}{%
% calling this multiple times for the same figure will result in it having multiple numbers assigned to it and multiply defined label issues
\begin{figure}%
\usebox{\csname savedfigure#1box\endcsname}%
\caption{#2}%
\label{savedfigure#1}%
\end{figure}}}
% use \reusefigure if the figure has already been shown, and you want to show it again
\newcommand\reusefigure[2]{% parameters #1=label name, #2=new caption
\@ifundefined{savedfigure#1box}{\errmessage{figure #1 hasn't been saved yet}}{%
% no easy way to test if the figure has been used or not yet, but will be numbered Figure 0 if not!
\begin{figure}%
\usebox{\csname savedfigure#1box\endcsname}%
\reusefigurecounter{savedfigure#1}%
\caption{#2}%
\end{figure}}}
\makeatother
\begin{document}
\begin{savefigure}{test}
World.
\end{savefigure}
\begin{frame}{First Frame}
\begin{figureandsave}{myfigure}{Description.}
\centering
\begin{tikzpicture}
\draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
\end{tikzpicture}
\end{figureandsave}
\pause
Some text after a pause.
\end{frame}
\begin{frame}{In between}
\begin{figure}
A different figure
\caption{For testing}
\end{figure}
\pause
\figurefirstuse{test}{Hello}
\reusefigure{test}{Hello again}
\end{frame}
\begin{frame}{Other Frame}
\reusefigure{myfigure}{Description (again).}
\begin{figure}
A second figure on the same frame.
\caption{With a number}
\end{figure}
More text.
\end{frame}
\end{document}