如何制作由叠加图层组成的图表,其中查看者可以独立于其他图层使每个图层可见或不可见?

如何制作由叠加图层组成的图表,其中查看者可以独立于其他图层使每个图层可见或不可见?

这个问题导致了一个新的方案的出现:
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}

相关内容