有没有通用的方法来找到宏评估的深度?例如,考虑以下脚本,
\documentclass{beamer}
\usepackage{mathtools}
\usepackage{calc}
\begin{document}
\begin{frame}
\newcommand*{\ofSize}[2]{\hphantom{####2}\llap{####1}}
x \alt<1>{\ofSize{apples}{oranges}}{oranges} \uncover<1-2>{done.}
\end{frame}
\end{document}
我希望在两个表达式之间交替,这样就不会导致周围的文本在动画过程中移动,并给出一个更通用的解决方案Beamer 中的动画方程。如您所见,我需要对第一个参数进行转义#1
三次(####1
)才能使其正常工作。
我使用的流程是任意的;我只是不断添加#
直到它不再给我错误。显然,如果在“更深”的嵌套宏级别中进行有意义的扩展,这可能会失败并产生可怕的副作用#1
。编写此类命令时是否有最佳实践/方法?
答案1
细节相当复杂。但基本上将环境beamer
的内容读取frame
为参数,这个过程将一对 简化##
为一个#
;但现在你的\newcommand
被作为另一个命令的参数给出,因此标记#
需要加倍。
配对意味着你需要四 #
字符来表示其中之一。
解决方案是在序言中执行此操作。
\documentclass{beamer}
\usepackage{mathtools}
\usepackage{calc}
\newcommand*{\ofSize}[2]{\leavevmode\hphantom{#2}\llap{#1}}
\begin{document}
\begin{frame}
x \alt<1>{\ofSize{apples}{oranges}}{oranges} \uncover<1-2>{done.}
\end{frame}
\end{document}
不要忘记初始的\leavevmode
,因为\hphantom
不是段落的开头,因此如果\ofSize
没有像示例应用程序中那样以某个段落的开头开头的内容开头,那么您就不会得到预期的结果。
答案2
egreg 已经很好地解释了处理框架时发生的情况beamer
。除了将宏定义移出环境之外frame
,还有另一种方法可以将框架标记为[fragile]
:
\documentclass{beamer}
\usepackage{mathtools}
\usepackage{calc}
\begin{document}
\begin{frame}[fragile]
\newcommand*{\ofSize}[2]{\leavevmode\hphantom{#2}\llap{#1}}
x \alt<1>{\ofSize{apples}{oranges}}{oranges} \uncover<1-2>{done.}
\end{frame}
\end{document}
使用fragile
,beamer
以不同的方式处理框架:基本上,它会吞噬内容并将其写入外部文件(扩展名为.vrb
)。然后我将文件作为“引擎”宏的参数,引擎会根据需要多次读取它。这样,就可以避免与宏参数相关的所有问题(例如逐字材料)。
缺点是处理时间会稍微长一些。优点是您可以在适当的情况下将宏定义保留在框架的本地。我倾向于经常这样做,因为它可以降低在另一个演示文稿中重复使用框架时忘记某些宏的风险。