提取 Beamer 覆盖规范中逻辑上第一个幻灯片?

提取 Beamer 覆盖规范中逻辑上第一个幻灯片?

在为演讲编写 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

编辑:

我正在尝试使用xparsexstring要构建的包\firstslideof,出于某种原因,我决定将其重命名为\extract。基本思想是解析幻灯片规范中每个范围的左端点并将其评估为数值。具有最小值的幻灯片规范应作为“第一张幻灯片”返回。例如,当的值小于 5\extract<+-+(1), 3, +, +(-2)-8>时应返回,否则应返回。+(-2)beamerpauses3

这是我目前拥有的代码:

\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。然后我们将此调用标记为已发生,以便下次测试将失败并且不会发生警报。

就在写这篇文章的时候,我能想到很多不太极端的情况,这些情况都会失败,但这至少是一个开始。

首次行动时发出警报

相关内容