![投影机中的解释气泡](https://linux22.com/image/258856/%E6%8A%95%E5%BD%B1%E6%9C%BA%E4%B8%AD%E7%9A%84%E8%A7%A3%E9%87%8A%E6%B0%94%E6%B3%A1.png)
在下面的 MWE 中,我想放置一个“解释气泡”(见下面插入的图片),指向第 8 行中的单词“Integer”(气泡应该叠加在文本上,如果气泡后面的文本仍然隐约可见,则透明效果会很好,但如果这会使事情变得更加复杂,则这绝不是必要的)。
实现这一目标的最简单、最优雅的解决方案是什么?
\documentclass[10pt,xcolor=dvipsnames]{beamer}
\usepackage{lipsum}
\begin{document}
\frame{\frametitle{A Modern Exegesis of Lipsum}
\lipsum[1]
\begin{itemize}
\item WDQGCBIOZBWIWURZBBTBRTTVVUQRWXWTVEWQVY
\item BXWZTVWQTVCWRCQTVXTTQVRQXTRCVCVRTCVVTX
\item AUXZWTCVWVWUTVRTVCUZTEVWTVCUTVTVERVCTV
\end{itemize}
}
\end{document}
MWE 的 pdf 输出:
气泡看起来应该像这样:
附言:我看见了投影仪中的简单对话气泡、箭头或气球状形状但对我来说这似乎相当复杂——希望有一个更简单的解决方案来解决我的问题。如果解决方案涉及 TikZ,请提供一些解释,因为我从未使用过 TikZ。注意:解决方案应该与标准兼容LaTeX
,最好不需要PDFLaTeX
。
编辑:有一个后续问题指向嵌套节点的 TikZ 标注。该问题的公认答案还为上述问题提供了另一种解决方案,该解决方案与beamer
下面建议的解决方案相结合可能更为稳健。
答案1
这是一个可能的解决方案:
\documentclass[10pt,xcolor=dvipsnames]{beamer}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts}
\usepackage{xparse}
\tikzset{
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}} % \pgfkeysalso doesn't change the path
},
}
\NewDocumentCommand{\mycallout}{r<> O{opacity=0.8,text opacity=1} m m}{%
\tikz[remember picture, overlay]\node[align=center, fill=cyan!20, text width=2cm,
#2,visible on=<#1>, rounded corners,
draw,rectangle callout,anchor=pointer,callout relative pointer={(230:1cm)}]
at (#3) {#4};
}
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=-0.5ex] \node (#1) {};}
\begin{document}
\begin{frame}{A Modern Exegesis of Lipsum}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum
gravida mauris. Nam arcu libero, nonummy eget, consectetuer id,
vulputate a, magna. Donec vehicula augue eu neque. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus
vestibulum urna fringilla ultrices. Phasellus eu tellus sit amet tortor
gravida placerat. Integer\tikzmark{int} sapien est, iaculis in, pretium quis, viverra ac,
nunc. Praesent eget sem vel leo ultrices bibendum. Aenean\tikzmark{second} faucibus.
Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur
auctor semper nulla. Donec varius orci eget risus. Duis nibh mi, congue
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci
dignissim rutrum.
\mycallout<2>{int}{Example: 2 is integer, but $\pi$ not}
\mycallout<3>[opacity=1]{second}{Example: 2 is integer, but $\pi$ not}
\begin{itemize}
\item WDQGCBIOZBWIW\mycallout<4>{0,0.5}{Another bubble placed with coordinates}URZBBTBRTTVVUQRWXWTVEWQVY
\item BXWZTVWQTVCWRCQTVXTTQVRQXTRCVCVRTCVVTX
\item AUXZWTCVWVWUTVRTVCUZTEVWTVCUTVTVERVCTV
\end{itemize}
\end{frame}
\end{document}
结果:
此解决方案几乎与使用 beamer 将 TikZ 云移动到更好的位置:首先标记将出现标注的单词,然后在该位置声明标注。
该\mycallout
命令的定义符合您的要求:默认情况下,即使我认为最好将其设置为不透明,其后面的文本仍然可见。出于这个原因,我让用户可以这样做:在可选的第二个参数中,只需将不透明度设置为 1,如示例中所示。
请注意,为了获得结果,需要进行两次编译运行:第一次计算标记的位置,第二次绘制标注。
代码说明
让我们一步一步分析所需的 TikZ 代码。除了库之外,我们首先遇到
\tikzset{
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}} % \pgfkeysalso doesn't change the path
},
}
这段代码取自思维导图 tikzpicture 在 beamer 中 (逐步显示)(我添加了一个,text opacity
因为它使该方法更加健壮):它是一种正确显示基于 TikZ 的动画的方法。我的意思是正确地?基于TikZ的动画可能会受到所谓的跳跃效应(在这个网站上你可以找到几个关于这方面的问题链接到问题) 并且该代码解决了这个问题。他实际上所做的是强制节点和路径的可见性在它们不应该可见时完全透明:您可以通过使用 键选择覆盖规范来决定节点和路径应该在何处可见visible on=<overlay specifications>
。
现在让我们看一下:
\NewDocumentCommand{\mycallout}{r<> O{opacity=0.8,text opacity=1} m m}{%
\tikz[remember picture, overlay]\node[align=center, fill=cyan!20, text width=2cm,
#2,visible on=<#1>,
draw,rectangle callout,anchor=pointer,callout relative pointer={(230:1cm)}]
at (#3) {#4};
}
这是负责创建标注的命令。正如评论中所说,他需要一些参数:
- 一个带有分隔符的强制性参数,
<>
用于决定正确的覆盖规范(与您使用 Beamer 插入它们类似),实际上是上一段所述的可见性不透明,但节点或路径是不透明的; - 第二个可选参数,可以选择背景和标注中要放置的文本的不透明度;
- 第三个参数是强制性的:它是标注指针的起始锚点(它可以只是一个节点或一个坐标);
- 第四个参数是强制性的:它是标注的文本。
节点使用语法实现\tikz[options]\node[options]at(pos){text};
;要传递给的选项\tikz
是,remember picture,overlay
因为标注应在覆盖层中绘制,并remember picture
允许记住以前的节点,例如用命令标记的节点\tikzmark
。传递给节点的选项只是创建标注所需的选项draw,rectangle callout,anchor=pointer,callout relative pointer={(230:1cm)}
,以修复其方面align=center, fill=cyan!20, text width=2cm,
并设置其可见性#2,visible on=<#1>,
(回想一下,#2
默认情况下是opacity=0.8,text opacity=1
)。请注意,实际上,用于覆盖层的代码会自行设置节点的不透明度(完全不透明或透明),因此为了避免出现问题,应事先声明标注的不透明度。
最后我们有\tikzmark
命令:
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=-0.5ex] \node (#1) {};}
它只是定义了一个带有标签的空节点:该节点与基线对齐,基线垂直放置在一条线的中间。节点将通过您为其指定的标签被记住,随后用作调出指针的起点。
互动词语解释
在提出建议之后聊天Speravir 提供了一个交互式解决方案:它基于ocgx
包和一些想法窃取自 交互式 PDF、Latex 和未来文章。
代码:
\documentclass[10pt]{beamer}
\usepackage{lmodern}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts,ocgx}
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=0.5ex] \node (#1) {};}
% \explainword: #1= identifier to mark the word, #2 text
\NewDocumentCommand{\explainword}{r[] m}{
\switchocg{#1}{#2}\tikzmark{#1}
}
\tikzset{my callout style/.style={
draw,rectangle callout,anchor=pointer,callout relative pointer={(230:1cm)},
rounded corners,align=center,text width=2cm,fill=cyan!20,
}
}
% \mycallout: #1 opacity style, #2 pointer base position, #3= text
\NewDocumentCommand{\mycallout}{O{opacity=0.8,text opacity=1} m m}{%
\begin{tikzpicture}[remember picture, overlay]
\begin{scope}[ocg={ref=#2,status=invisible,name={#3}}]
\node[my callout style,#1]at (#2) {#3};
\end{scope}
\end{tikzpicture}
}
\begin{document}
\begin{frame}{A Modern Exegesis of Lipsum}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum
gravida mauris. Nam arcu libero, nonummy eget, consectetuer id,
vulputate a, magna. Donec vehicula augue eu neque. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus
vestibulum urna fringilla ultrices. Phasellus eu tellus sit amet tortor
gravida placerat. \explainword[int]{Integer} sapien est, iaculis in, pretium quis, viverra ac,
nunc. Praesent eget sem vel leo ultrices bibendum. \explainword[second]{Aenean} faucibus.
Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur
auctor semper nulla. Donec varius orci eget risus. Duis nibh mi, congue
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci
dignissim rutrum.
\mycallout{int}{Example: 2 is integer, but $\pi$ not}
\tikzset{my callout style/.append style={fill=orange!20}}
\mycallout[opacity=1]{second}{Example: 2 is integer, but $\pi$ not}
\begin{itemize}
\item WDQGCBIOZBWIWURZBBTBRTTVVUQRWXWTVEWQVY
\item BXWZTVWQTVCWRCQTVXTTQVRQXTRCVCVRTCVVTX
\item AUXZWTCVWVWUTVRTVCUZTEVWTVCUTVTVERVCTV
\end{itemize}
\end{frame}
\end{document}
它是如何工作的?现在不需要覆盖规范,因为命令的\explainword
实现方式是,它实际上是一个 ocgx 按钮,当单击单词时,它能够显示标注。它需要两个参数:第一个是标识符(用于宏\tikzmark
和 ocgx 按钮),第二个是要解释的文本/单词。
当单击示例中的两个单词时,结果是:
笔记
这总是需要两次编译运行,而且对我来说,该解决方案仅适用于 Adobe Reader。
顺便说一句:我对标注的样式进行了更好的组织,现在可以更轻松地进行定制(请参阅第二项工作的解释)。