这个问题导致了一个新的方案的出现:
ocgx
(我已将问题编辑为ocg工具看起来这是正确的选择,而不是动画。
我正在尝试使用乳胶与蒂克兹包来制作由四个层组成的图表。规范要求查看器可以显示或隐藏任何层,因此每个层都需要自己的开/关开关。
这动画包提供了一组控制按钮,适用于需要按预定顺序添加图层的应用程序。我早期尝试制作图表时尝试使用一个动画内联每个层的环境,以便每个层都有自己的一组控制按钮。
我尝试了使用两个层的测试用例动画内联环境,每个都只显示一个空白画布或一个图层,并且每个都有自己的一组控制按钮。各种尝试都不令人满意,包括
尝试 1:在图形环境中,将 animateinline 环境嵌套在另一个环境中。这会导致编译警告,如果忽略该警告,则不会产生任何输出。
尝试 2:在一个图形环境中放置两个独立的 animateinline 环境 - 每组单选按钮独立运行。为了确保第二层叠加在第一层上,我使用 \vspace 手动将第二张图形移动到与第一张图形相同的页面上位置。不幸的是,第二张图形用白色背景完全覆盖了第一张图形,因此看起来第一组单选按钮不起作用,只是因为看不到第一层!
这种尝试存在各种问题:它需要手动摆弄来叠加图层,需要以某种方式使图层透明,即使这样做也意味着控制按钮是叠加的,因此有必要找到一种方法来改变一组控制按钮的位置。
现在发布的答案表明ocg工具将提供一个不需要手动操作的框架,允许透明层,并允许图表创建者放置可以使每个单独的层可见或不可见的链接。一旦我确定该建议符合我的需求,我会报告并使这个问题更简洁。
下面是使用以下方法进行的不令人满意的尝试 2 的一些代码动画。取消注释 vspace 命令会显示不透明的第二层位于第一层之上并遮挡第一层的问题。
\documentclass{article}
\usepackage{color,tikz,fancyvrb,animate}
\usetikzlibrary{matrix,fit,calc}
\begin{document}
% An experiment to get diagram layers that can be controlled individually, not just presented sequentially as I've done in "animate".
% I think this could be a passable solution if I could get the layers to be transparent rather than the top one blocking the bottom one.
\begin{figure}
\centering
% Sample_timeline determines the sequence in which frames are added
\begin{VerbatimOut}{Sample_timeline}
::0x0
::1x0
\end{VerbatimOut}
\begin{animateinline}[
step,controls,timeline=Sample_timeline,
begin={%
\begin{tikzpicture}%
\useasboundingbox (-0.5,-0.5) rectangle (6,5.5);%
},
end={\end{tikzpicture}}
]{1} %although not relavant (option `step') fps is required argument
\draw[blue] (-0.5,-0.5) rectangle (4,4.5);
\newframe
\draw[blue] (0,0) circle(0.2) node (circcentre) {layer 1};
\end{animateinline}
% Having this command uncommented causes a problem as the second graphic covers the first - so it appears that the buttons for the first graphic don't work.
% This destroys the illusion of two layers which can be turned on and off independently of each other. Maybe the problem can be
% resolved if the "layers" can be made transparent.
%\vspace{-5.5cm}
% Sample_timeline2 determines the sequence in which frames are added
\begin{VerbatimOut}{Sample_timeline2}
::0x0
::1x0
\end{VerbatimOut}
\begin{animateinline}[
step,controls, timeline=Sample_timeline2,
begin={%
\begin{tikzpicture}%
\useasboundingbox (-0.5,-0.5) rectangle (6,5.5);%
},
end={\end{tikzpicture}}
]{1} %although not relavant (option `step') fps is required argument
\draw[orange, line width=3pt] (-0.5,-0.5) rectangle (4,4.5);
\newframe
\node[draw,red] (reccentre) at +(2,2){layer 2};
\end{animateinline}
\end{figure}
\end{document}
答案1
最后编辑:在 Paul Isambert 的大力帮助下,我编写了这个ocgx
软件包。
这是一个带有包的示例ocgx
(可通过 CTAN 和 TeXLive 获得)。
三张截图:
代码:
\documentclass{beamer}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{ocgx,calc}
\begin{document}
\tikzset{ocg button/.style={circle,minimum size=.5em,switch ocg with mark on={#1}{}}}
\begin{frame}
\frametitle{Title}
\begin{tikzpicture}[overlay,remember picture,ocg={name=Layer 1,ref=layer1}]
\begin{scope}[shift={(current page)}]
\fill[red,fill opacity=.5] (120:1cm) circle [radius=1.5cm];
\end{scope}
\end{tikzpicture}
\begin{tikzpicture}[overlay,remember picture,ocg={name=Layer 2,ref=layer2}]
\begin{scope}[shift={(current page)}]
\fill[blue,fill opacity=.5] (240:1cm) circle [radius=1.5cm];
\end{scope}
\end{tikzpicture}
\begin{tikzpicture}[overlay,remember picture,ocg={name=Layer 3,ref=layer3}]
\begin{scope}[shift={(current page)}]
\fill[green,fill opacity=.5] (0:1cm) circle [radius=1.5cm];
\end{scope}
\end{tikzpicture}
\begin{itemize}
\item Layer 1 \tikz\node[fill=red!50,ocg button=layer1]{};
\item Layer 2 \tikz\node[fill=blue!50,ocg button=layer2]{};
\item Layer 3 \tikz\node[fill=green!50,ocg button=layer3]{};
\end{itemize}
\end{frame}
\end{document}
答案2
这是一个动画基于充当开关的链接的解决方案:
\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz}
\usepackage{animate}
\usepackage{hyperref}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% command to create toggle link to animation frame
\newcommand{\ShowHideFrame}[3]{%
% #1: anim No. (zero-based),
% #2: frame No. (zero-based),
% #3: link text
\leavevmode%
\pdfstartlink user {
/Subtype /Link
/Border [\@pdfborder]%
/A <<
/S/JavaScript
/JS (
\if@anim@useocg%
if(a#1.fr[#2].state==true){
a#1.fr[#2].state=false;
}else{
a#1.fr[#2].state=true;
}
\else
if (a#1.fr[#2].display==display.visible){
a#1.fr[#2].display=display.hidden;
}else{
a#1.fr[#2].display=display.visible;
}
this.dirty=false; %reset document status to `unchanged'
\fi
)
>>
}\strut{}#3%
\pdfendlink%
}
% command to create link that goes to particular frame while hiding
% the others
\newcommand{\GoToFrame}[3]{%
% #1: anim No. (zero-based),
% #2: frame No. (zero-based),
% #3: link text
\leavevmode%
\pdfstartlink user {
/Subtype /Link
/Border [\@pdfborder]%
/A <<
/S/JavaScript
/JS (
for (idx in a#1.fr) {
\if@anim@useocg
if(idx==#2){a#1.fr[idx].state=true;}else{a#1.fr[idx].state=false}
\else
if(idx==#2){a#1.fr[idx].display=display.visible;}else{a#1.fr[idx].display=display.hidden}
\fi
}
)
>>
}\strut{}#3%
\pdfendlink%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\begin{document}
\def\firstcircle{(0,0cm) circle (1.5cm)}
\def\secondcircle{(60:1.5cm) circle (1.5cm)}
\def\thirdcircle{(0:1.5cm) circle (1.5cm)}
\begin{center}
\begin{animateinline}[
step,
begin={
\begin{tikzpicture}
\useasboundingbox \firstcircle \secondcircle \thirdcircle;
},
end={\end{tikzpicture}}
]{1}
%empty 0th frame
\newframe
\fill[red,fill opacity=.5] \firstcircle;
\newframe
\fill[green,fill opacity=.5] \secondcircle;
\newframe
\fill[blue,fill opacity=.5] \thirdcircle;
\end{animateinline}
\GoToFrame{0}{0}{none} |
\ShowHideFrame{0}{1}{red} |
\ShowHideFrame{0}{2}{green} |
\ShowHideFrame{0}{3}{blue}
\end{center}
\end{document}