原始问题

原始问题

原始问题

在我正在编写的 Beamer 演示文稿中,我有一个itemize列表,并希望逐一显示每个项目。然后,在幻灯片上出现给定项目后,我希望以透明的方式重新覆盖该项目。使用 很容易实现这again covered一点\setbeamercovered

\documentclass{beamer}
\setbeamercovered{again covered={\opaqueness<1->{25}}}
\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item Who's on first
  \item What's on second
  \item I don't know's on third
  \end{itemize}
  \uncover<+->{-- Abbott and Costello}
\end{frame}
\end{document}

但这里有一个转折:我想修改上面的例子,这样,一旦被覆盖,单词“Who”、“What”、“I don't know”即使在它们各自的\items 被重新覆盖后仍然未被覆盖。以下代码尝试了三种不同的方法来实现这一点:

\documentclass{beamer}
\setbeamercovered{again covered={\opaqueness<1->{25}}}
\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item \uncover<.->{Who}'s on first
  \item {\color<.->{black} What}'s on second
  \item<+-> I don't know\uncover<.>{'s on third}
  \end{itemize}
  \uncover<+->{-- Abbott and Costello}
\end{frame}
\end{document}

在此处输入图片描述

前两次尝试根本不起作用。第三次尝试更接近,但仍然不太正确:我希望三角形项目标记在's on third被重新覆盖时保持透明。

所以,我的问题是:即使周围上下文被重新覆盖,我怎样才能干净而正确地保持某些子短语不被覆盖?

可能有一种方法可以挂接到项目标记并使其透明,但我想避免这种情况;我将使用带有推理规则的答案(用包设置lkproof),由于我的 TeX 知识有限,因此很难创建这样的钩子。

修改后的问题

@alexurba 的答案很有用,几乎满足了我的需求,但还不够。首先,我稍微修改了他的建议:

\newcommand<>{\myuncover}[1]{%
  \alt#2{\mbox{\beamer@endcovered #1}}{\mbox{#1}}}

通过使用\alt\mbox而不是使用\only\makebox[0pt][r],我们可以避免过度打印文本#1

但此命令与的交互效果不佳\color,如以下示例所示:

\documentclass{beamer}
\setbeamercovered{again covered={\opaqueness<1->{25}}}

\makeatletter
\newcommand<>{\alexurbauncover}[1]{%
  #1\only#2{\makebox[0pt][r]{\beamer@endcovered #1}}}

\newcommand<>{\myuncover}[1]{%
  \alt#2{\mbox{\beamer@endcovered #1}}{\mbox{#1}}}
\makeatother

\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item Who's on {\color{structure} first}
  \item \myuncover<.->{What}'s on {\color{structure} second}
  \item \alexurbauncover<.->{I don't know}'s on {\color{structure} third}
  \end{itemize}
  \uncover<+>{-- Abbott and Costello}
\end{frame}
\end{document}

在此处输入图片描述

第一个项目符号显示了普通的\uncover重新覆盖,这使得structure彩色文本在重新覆盖时变得适当透明。第二个项目符号显示修订后的\myuncover命令以某种方式破坏了彩色文本的这种处理structure:它在重新覆盖时保持完全不透明。第三个项目符号显示这种行为不是我在修改@alexurba 的原始版本时无意中引入的\myuncover

因此,我修改后的问题是:我怎样才能得到类似上述内容\myuncover并正确尊重\color重新覆盖文本中的切换?

尝试的解决方案

据我所知,在上面的 中\myuncover\mbox似乎起到了划定 的范围的作用\beamer@endcovered。另一种想法是结束然后重新启动覆盖行为,例如使用

\newcommand<>{\myuncover}[1]{%
  \alt#2{\beamer@endcovered #1\beamer@startcovered}{#1}}

但是,这个命令并不像我希望的那样工作:

\documentclass{beamer}
\setbeamercovered{again covered={\opaqueness<1->{25}}}

\makeatletter
\newcommand<>{\myuncover}[1]{%
  \alt#2{\beamer@endcovered #1\beamer@startcovered}{#1}}
\makeatother

\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item \myuncover<.->{Who}'s on {\color{structure} first}
  \item \myuncover<.->{What}'s on {\color{structure} second}
  \item \myuncover<.->{I don't know}'s on {\color{structure} third}
  \end{itemize}
  \uncover<+>{-- Abbott and Costello}
\end{frame}
\end{document}

在此处输入图片描述

我猜是\beamer@startcovered阻止了 Beamer 识别's on first正在被重新覆盖的等,因此again covered无法在正确的时间点启动。但这只是猜测,因为我不了解具体\beamer@startcovered工作原理。

答案1

编辑5

根据 OP 的建议,另一种解决方案是中断覆盖并重新启动它(与本地揭露文本相反)。这可以通过以下宏来完成:

\newcommand<>{\myinterruptcover}[1]{%
  \expandafter\ifx%
    \csname beamer@doafter\the\beamer@coveringdepth\endcsname\relax
  #1%
  \else
  \alt#2{\beamer@endcovered #1\beamer@startcovered}{#1}%
  \fi
}

条件检查我们当前是否处于覆盖区域,即是否\beamer@doafter<N>(见下文)被定义。

我仍然更喜欢\myuncover宏,因为它只是局部撤消覆盖物的颜色变化。

编辑4

@Henry DeYoung 要求我解释一下如何想出这个宏。我在下面添加了一个相当长的解释。

编辑3

在对光束源进行进一步挖掘之后,我得出了以下结论,它还保留了结构颜色(通过使用局部颜色定义):

\documentclass{beamer}

\makeatletter
\newcommand{\my@endcovered}{%
  % check if \beamer@doafterN is different from \relax
  % where N is the current covering level
  \expandafter\ifx%
    \csname beamer@doafter\the\beamer@coveringdepth\endcsname\relax
  \else
  % reset the color hook, but only locally
  % -- in the 'real' \beamer@doafter the global \xdef is used 
  %    instead of \edef
  \edef\beamer@colorhook{%
    \csname beamer@oldcolorhook\the\beamer@coveringdepth\endcsname}%
  % I think the following is not needed here, though I don't really
  % know what effect it has
  % \edef\beamer@pgfextension{%
  %  \csname beamer@oldpgfextension\the\beamer@coveringdepth\endcsname}%
  % finally, set colors
  \color{.}%
  \fi%
}%
\newcommand<>{\myuncover}[1]{\alt#2{{\my@endcovered #1}}{#1}}
\makeatother

\setbeamercovered{again covered={\opaqueness<1->{25}}}

\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item \myuncover<.->{Who}'s on {\color{structure} first}
  \item \myuncover<.->{What}'s on {\color{structure} second}
  \item \myuncover<.->{I don't know}'s on {\color{structure} third}
  \end{itemize}
  \uncover<+>{-- Abbott and Costello}
\end{frame}
\end{document}

在此处输入图片描述

我认为这可以解决所有问题。

解释

beamer 命令\uncover (与所有与叠加特征相关的命令一样)定义beamerbaseoverlay.sty

\newcommand{\uncover}{\alt{\beamer@fakeinvisible}{\beamer@makecovered}}

因此\beamer@makecovered当覆盖规范匹配时会触发该宏。该宏又定义在与

\long\def\beamer@makecovered#1{\beamer@startcovered#1\beamer@endcovered}

这就是为什么我首先建议在局部使用\beamer@endcovered来结束覆盖。但是,\beamer@endcovered有一些不理想的全局影响,因此有必要更深入一点。查看宏定义

\def\beamer@endcovered{%
  \beamer@smuggle{%
  \csname beamer@doafter\the\beamer@coveringdepth\endcsname%
  \global\advance\beamer@coveringdepth by -1\relax%
  }%
}%

我们看到\beamer@endcovered基本上扩展为\beamer@doafter<N>,其中<N>是计数器的当前值\beamer@coveringdepth,它跟踪覆盖级别。最后,该计数器减少 1。正如来源中的评论所说,\beamer@smuggle用于“偷运跳过”,我决定暂时忽略这一点(如果有人读到这篇文章并知道更多,请纠正我)。

现在它变得有点复杂了:每个\beamer@doafter<N>都有一个对应的\beamer@do。两个宏都定义为\beamer@actions

\def\beamer@actions#1#2{%
  \gdef\beamer@do{#1%
    \expandafter\gdef\csname beamer@doafter%
    \the\beamer@coveringdepth\endcsname{#2}}}

在 中执行\beamer@startcovered。如您所见,实际上doafter宏是在do展开时定义的。来自 的相关代码片段\beamer@starcovered位于 的定义中\opaqueness

\def\opaqueness<##1>##2{%
\only<##1>{%
  \beamer@actions{%
    \expandafter\xdef\csname beamer@oldcolorhook%
    \the\beamer@coveringdepth\endcsname{\beamer@colorhook}%
    \expandafter\xdef\csname beamer@oldpgfextension%
    \the\beamer@coveringdepth\endcsname{\beamer@pgfextension}%
    {\globalcolorstrue\colorlet{beamer@freeze\the\beamer@coveringdepth}{bg}}%
    \xdef\beamer@colorhook{!##2!beamer@freeze%
      \the\beamer@coveringdepth\beamer@colorhook}%
    \gdef\beamer@pgfextension{!##2opaque}%
    \color{.}%
  }%
  {%
    \xdef\beamer@colorhook{\csname beamer@oldcolorhook%
      \the\beamer@coveringdepth\endcsname}%
    \xdef\beamer@pgfextension{\csname beamer@oldpgfextension%
      \the\beamer@coveringdepth\endcsname}%
    \color{.}%
  }}}%

这里,\beamer@actions如果覆盖规范匹配,则调用。然后将宏\beamer@do\beamer@doafter<N>设置为参数。现在很明显,宏\beamer@do负责设置覆盖对象的颜色(这取决于用户设置)。先前的颜色钩子保存到名为的宏中\beamer@oldcolorhook<N>,其中<N>再次是覆盖级别。当\beamer@doafter展开时,将准确恢复此颜色钩子:

    \xdef\beamer@colorhook{\csname beamer@oldcolorhook%
      \the\beamer@coveringdepth\endcsname}%
    \xdef\beamer@pgfextension{\csname beamer@oldpgfextension%
      \the\beamer@coveringdepth\endcsname}%
    \color{.}%

这些就是我们想要的代码行。我只是 \xdef用局部代码替换了全局代码\gdef,以限制颜色重新定义的范围。

最后只缺少一点:如上所述,只有当中的\beamer@doafter覆盖规范(的\only\opaqueness匹配时,的定义才为真。如果不是这种情况,则宏不会执行任何操作,并且等于\relax。所以我的宏检查是否\beamer@doafter等于,\relax在这种情况下它也不会执行任何操作。


编辑2

现在这应该真正产生期望的结果:

\documentclass{beamer}
\setbeamercovered{again covered={\opaqueness<1->{25}}}
\makeatletter
\newcommand*{\myuncover}[1]{%
#1\only<.->{\makebox[0pt][r]{\beamer@endcovered #1}}%
}
\makeatother
\begin{document}
\begin{frame}{Frame Title}
  \begin{itemize}[<+>]
  \item \myuncover{Who}'s on first
  \item \myuncover{What}'s on second
  \item \myuncover{I don't know}'s on third
  \end{itemize}
  \uncover<+>{-- Abbott and Costello}
\end{frame}
\end{document}

在此处输入图片描述

相关内容