在为演讲编写 Beamer 幻灯片时,我发现我经常希望在幻灯片组中显示一些文本(通常是数学),并且仅在该组中的第一张幻灯片上收到提醒。例如,我可以使用 、 等来实现这$1 + 1 = \action<visible@+- | alert@+>{2}$
一点$2 + 2 = \action<visible@.(-1)- | alert@.(-1)>{4}$
。
但是,如果可以将这些操作合并为一个操作,则更易于维护和阅读alertvisible
。使用简单的宏,可以轻松处理幻灯片组具有以下形式的情况<slide number>-
:
\documentclass{beamer}
\newcommand{\alertvisible}[1]{visible@#1- | alert@#1}
\begin{document}
\begin{frame}{Frame Title}
Facts:\pause
\begin{itemize}
\item $1 + 1 = \action<visible@+- | alert@+>{2}$
\item $2 + 2 = \action<\alertvisible{+}>{4}$
\item $3 + 3 = \action<\alertvisible{.(-1)}>{6}$
\item $4 + 4 = \action<\alertvisible{+}>{8}$
\end{itemize}
\end{frame}
\end{document}
不幸的是,这个简单的解决方案不能处理一般情况。例如,我可能想要一个alertvisible
动作,这样\action<alertvisible@+,+(2)-+(3)>
就相当于\action<visible@+,+(2)-+(3) | alert@+>
。这似乎需要一种方法,比如说\firstslideof
,提取组中逻辑上第一个幻灯片,这样就可以定义
\newenvironment<>{alertvisibleenv}%
{\begin{visibleenv}#1\begin{alertenv}\firstslideof{#1}}%
{\end{alertenv}\end{visibleenv}}
是否有某种方法可以定义\firstslideof
以允许这种一般定义alertvisibleenv
?
编辑:
我正在尝试使用xparse
和xstring
要构建的包\firstslideof
,出于某种原因,我决定将其重命名为\extract
。基本思想是解析幻灯片规范中每个范围的左端点并将其评估为数值。具有最小值的幻灯片规范应作为“第一张幻灯片”返回。例如,当的值小于 5\extract<+-+(1), 3, +, +(-2)-8>
时应返回,否则应返回。+(-2)
beamerpauses
3
这是我目前拥有的代码:
\documentclass{beamer}
\usepackage{etoolbox}
\usepackage{etextools}
\usepackage{xparse}
\usepackage{xstring}
\makeatletter
\NewDocumentCommand{\extract}{>{\SplitList{,}}r<>}{%
% Initially set the minimum slide spec to something large
\def\beamer@extract@min{+(1000)}%
\ProcessList{#1}{\beamer@extract}%
}
\newcommand*{\beamer@extract}[1]{%
% Substitute \beamer@extract@groupplus for each +
\saveexpandmode
\expandarg
\StrSubstitute{#1}{+}{\noexpand\beamer@extract@groupplus}[\@tmpa]%
\restoreexpandmode
%
% Once \@tmpa is fully expanded, each occurrence of
% a possibly shifted + will be surrounded with { }.
% The { } are used to prevent \beamer@@extract from
% incorrectly splitting +(-1) as +( and 1).
%
%% How do I fully expand \@tmpa here? Is this right?
\ExpandNext{\beamer@@extract}{\@tmpa}%
}
\NewDocumentCommand{\beamer@@extract}{>{\SplitArgument{1}{-}}m}{%
% Use \SplitArgument and \@firstoftwo to get left endpoint
% of range.
Found: `\@firstoftwo#1'\par
%
% Evaluate the prospective and current minima to
% a numeric value and store the result in \@tmpa
% and \@tmpb, respectively.
\beamer@@extract@eval{\@tmpa}{\@firstoftwo#1}%
\beamer@@extract@eval{\@tmpb}{\beamer@extract@min}%
%
% If the prospective minimum is smaller, then
% make it the current minimum.
\ifnumless{\@tmpa}{\@tmpb}{%
\expandnext{\def\beamer@extract@min}{\@firstoftwo#1}%
Updated
}{%
Not Updated
}%
Minimum: \meaning\beamer@extract@min\par
}
\newcommand*{\beamer@@extract@eval}[2]{%
% Substitute \beamer@@extract@evalplus for each occurrence of
% + in #2, storing the fully expanded result in #1.
\saveexpandmode
\expandarg
\StrSubstitute{#2}{+}{\noexpand\beamer@@extract@evalplus}[#1]%
\restoreexpandmode
%% How do I fully expand #1 here?
}
\NewDocumentCommand{\beamer@@extract@evalplus}{r()}{%
\value{beamerpauses}+#1%
}
\NewDocumentCommand{\beamer@extract@groupplus}{D(){0}}{%
{+(#1)}%
}
\makeatother
\begin{document}
\begin{frame}{Test Frame}
% The following should set \beamer@extract@min to
% +(-2) if beamerpauses < 5
% 3 if beamerpauses >= 5
\extract<+-+(1), 3, +, +(-2)-8>
\end{frame}
\end{document}
不幸的是,当我运行代码时,出现错误:You can't use \numexpr in horizontal mode. \ifnumcomp ...\ifnum \numexpr #1\relax #2\numexpr #3\relax \expandafter \@fi...
。我猜测该错误是由于上面标有的行中的扩展问题造成的%%
。
问题:
问题确实与扩展有关吗?如果是,我该如何解决?
答案1
我有一种方法可以供您使用,我认为这种方法可能相当灵活,并且不需要深入研究叠加规范。但是,它可能有点粗糙,可能需要进行一些改进(这有点浪费宏,计数器可能应该actiononfirst
每帧重置一次)。
代码如下:
\documentclass{beamer}
%\url{https://tex.stackexchange.com/q/61975/86}
\makeatletter
\newcounter{actiononfirst}
\resetcounteronoverlays{actiononfirst}
\newcommand<>\alertvisible[1]{%
\stepcounter{actiononfirst}%
\only<1>{%
\expandafter\gdef\csname
actiononfirst\the\value{actiononfirst}\endcsname{0}%
}%
\let\my@action=\pgfutil@firstofone
\only#2{%
\ifnum\csname
actiononfirst\the\value{actiononfirst}\endcsname=0\relax
\let\my@action\alert
\expandafter\gdef\csname
actiononfirst\the\value{actiononfirst}\endcsname{1}%
\fi
}%
\visible#2{\my@action{#1}}%
}
\makeatother
\begin{document}
\begin{frame}{Frame Title}
\action<alertvisible@+->{hereon}
\action<alertvisible@1,3->{hereoff}
Facts:\pause
\begin{itemize}
\item $1 + 1 = \action<visible@+- | alert@+>{2}$
\item $2 + 2 = \action<alertvisible@+>{4}$
\item $3 + 3 = \action<alertvisible@.(-1)>{6}$
\item $4 + 4 = \action<alertvisible@+>{8}$
\end{itemize}
\end{frame}
\end{document}
解释如下:
我们定义了一个覆盖感知命令,\alertvisible
作为新的动作(根据 Ulrike 在如何添加改变参数的自定义投影仪操作?)。计数器 会索引每个调用(可以基于每张幻灯片,而且如果其中一个进入 ,则可能会出现问题,\only
从而干扰计数)actiononfirst
。每个调用都有一个对应的宏,其形式\actiononfirst<index>
为 ,记录此调用是否以前见过。此宏在第一张幻灯片上设置为0
(如果由于某种原因跳过第一个覆盖,则可能会导致问题)。现在是重要的部分。覆盖规范作为第二个参数传递给我们的\alertvisible
命令。我们将其用作命令的覆盖规范,\only
从而确保仅在应显示文本时才运行此命令 - 这避免了我遇到的问题(并在评论中提到),即使\visible
文本不可见,也始终会处理带有参数的调用。在 中,\only
我们测试以查看我们是否以前被调用过(通过测试\actiononfirst<index>
),如果没有,则我们将辅助宏设置为\alert
。否则它只是\pgfutil@firstofone
。然后我们将此调用标记为已发生,以便下次测试将失败并且不会发生警报。
就在写这篇文章的时候,我能想到很多不太极端的情况,这些情况都会失败,但这至少是一个开始。