4

I'm trying to use visible on style defined by Qrrbrbirlbel with an automatic increment overlay <-+>. However, when I do so the nodes and the edges are incremented separately. I blame the lines

/tikz/visible on={#1},
edge={/tikz/visible on={#1}}

that apply the passed range to the edge and nodes separately. However, I don't know how to send the same auto-increment to both of them simultaneously. Another way may be to decrement the counter, but I'm not familiar with beamer overlays to know which parts to tweak.

How can I achieve such endeavor?

I took this code to show the behavior I described. I'm trying to make the tree appear a node (and its corresponding edge) at a time.

\documentclass{beamer}
\usepackage{forest}

\setbeamertemplate{navigation symbols}{} %Remove navigation bar
\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
    },
}
\forestset{
  visible on/.style={
    for children={
      /tikz/visible on={#1},
      edge={/tikz/visible on={#1}}}}}

\begin{document}
\begin{frame}[plain]{Same with forest}
  \begin{forest}
    [VP, calign=last, visible on=<+->
      [{[ajout]}\\\textit{rapidement}, 
      align=center,
      base=top, visible on=<+->, ]
      [VP, calign=first, visible on=<3->, 
        [VP, calign=first, visible on=<2->, 
          [V\\\textit{mange}, align=center,base=top, visible on=<1->, ]
          [{[compl]}\\\textit{une orange}, align=center,base=top, visible on=<1->, ]
        ]
        [{[ajout]}\\\textit{dans la cuisine}, align=center, visible on=<2->,]
      ]
    ]
  \end{forest}

\end{frame}
\end{document}

See the result using descendants (children produces the same result). Notice how the nodes appear first, and then edges start appearing. enter image description here

adn
  • 11,233
  • To be honest, I'm not very clear what you are trying to do. You *say* that you want to reveal the tree one node at a time, but your code uses for children which will affect multiple nodes unless no node has more than one child. Moreover, your visible on specifications don't make sense since applying such specifications to terminal nodes will obviously have no effect given that the style is only applied to children. – cfr Oct 28 '15 at 22:54
  • I just try to modified the version in which they reveal the tree bottom up. However, they do it using hard coded ranges, e.g., <2-> or <3->. I was hopping for something more automatic like <+->. Nevertheless, I tried it that way, and changed the ascendants for descendants or children but that has the problem that reveals the tree a node at a time, and an edge at a time. – adn Oct 28 '15 at 23:13
  • Well, you could reveal the whole tree a level at a time or a node at a time by specifying a style in the preamble, I think. To be honest, though, this is already rather fragile. Beamer seriously mutilates TeX's output in various ways and getting other things to play nicely with that, when they weren't designed for Beamer, is always going to run up against fairly serious limitations in what's possible. At least, that's my impression. – cfr Oct 29 '15 at 00:00

1 Answers1

2

I'm not sure what exactly you want to achive, but I understand the problem behind synchronous appearance of a node and its edge. As promised in the documentation of draw tree key (section 3.3.7), the nodes are drawn first, then edges and finally extra tikz code. The idea behind such order is that edges and tikz code should be able to refer to any node, but obviously this creates problem when using beamer's incremental overlay specification <+->.

Solution. The idea is to reset the value of counter beamerpauses before we start drawing the edges. Now, as forest offers no hook there (hmm ... an idea:) we must get creative.

  1. We put the code to save the beamerpauses counter inside the node options of the root node. (In this particular case, simply saving it during option processing would work, too, but the node options variant is more robust, it works also if the tree is drawn multiple times).

  2. We squeeze the code restoring the beamerpauses counter inside the first edge that will be drawn. One detail is straightforward: as the root node has no edge, we increase the counter by one. The other detail is not resolved automatically: forest has no idea which edge is the first one that will be drawn, so for first was specified manually.

Here's the code, hope it helps.

\documentclass{beamer}
\usepackage{forest}

\setbeamertemplate{navigation symbols}{} %Remove navigation bar
\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
    },
}
\forestset{
  visible on/.style={
    %for children={
      /tikz/visible on={#1},
      edge={/tikz/visible on={#1}}
   % }
  }
}

\begin{document}
\begin{frame}[plain]{Same with forest}
  \begin{forest}
    node options={/utils/exec={\xdef\mybeamerpauses{\thebeamerpauses}}},
    for first={edge={/utils/exec={\setcounter{beamerpauses}{\numexpr1+\mybeamerpauses}}}},
    [VP, calign=last, visible on=<+->
      [{[ajout]}\\\textit{rapidement}, 
      align=center,
      base=top, visible on=<+->, ]
      [VP, calign=first, visible on=<+->, 
        [VP, calign=first, visible on=<+->, 
          [V\\\textit{mange}, align=center,base=top, visible on=<+->, ]
          [{[compl]}\\\textit{une orange}, align=center,base=top, visible on=<+->, ]
        ]
        [{[ajout]}\\\textit{dans la cuisine}, align=center, visible on=<+->,]
      ]
    ]
  \end{forest}

\end{frame}
\end{document}

Actually, as it makes no difference when the visible on=<+-> is given, here's also a shorter version using for tree.

\documentclass{beamer}
\usepackage{forest}

\setbeamertemplate{navigation symbols}{} %Remove navigation bar
\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
    },
}
\forestset{
  visible on/.style={
    %for children={
      /tikz/visible on={#1},
      edge={/tikz/visible on={#1}}
   % }
  }
}

\begin{document}
\begin{frame}[plain]{Same with forest}
  \begin{forest}
    node options={/utils/exec={\xdef\mybeamerpauses{\thebeamerpauses}}},
    for first={edge={/utils/exec={\setcounter{beamerpauses}{\numexpr1+\mybeamerpauses}}}},
    for tree={visible on=<+->},
    [VP, calign=last
      [{[ajout]}\\\textit{rapidement}, 
      align=center,
      base=top ]
      [VP, calign=first
        [VP, calign=first
          [V\\\textit{mange}, align=center,base=top ]
          [{[compl]}\\\textit{une orange}, align=center,base=top ]
        ]
        [{[ajout]}\\\textit{dans la cuisine}, align=center]
      ]
    ]
  \end{forest}

\end{frame}
\end{document}
  • Very devious ;). I wasn't sure this was what the OP wanted, but it seems like the kind of thing it makes sense to want! – cfr Oct 29 '15 at 01:54
  • Yes that is what I was looking for. Thanks for your wizardry! – adn Oct 29 '15 at 10:17