13

I am trying build a tree bottom up in a beamer document, i.e. to draw it on screen starting from the most deeply embedded leaves. I've found a lot of Q&As and discussions on how to have trees unfold from the root, on this page and elsewhere, but what I'm trying to do is the reverse, and as far as I can tell many of the methods proposed don't work in this scenario - e.g., I can't seem to suppress a parent node while displaying the children in a standard tikz-tree.

Ideally, the method would use the size of the complete tree to compute positions all along so that the image doesn't wobble from slide to slide. I'm using qtree because it's what I grew up with, but I am very much open to solutions using other packages with different syntax.

What I've come up with are the following:

  1. Drawing the entire tree (in qtree or otherwise), and only revealing the nodes and leaves closer to the root later. Downside: The unlabeled skeleton of the tree remains visible throughout.

  2. Copy-pasting different size chunks of the tree, and using overprint to display them on successive slides of the same frame. Downside: The size of the largest, complete tree is inaccessible when the smaller subtrees are drawn, so need an extra step of pushing the smaller trees to the right and bottom to get them anywhere near on top of each other (my snapshot below isn't actually quite there).

So what I am looking for is either a variant of (1) that makes the higher edges invisible alongside with the suppressed nodes, or a variant of (2) that automatically extracts the dimensions of the largest tree and uses them as input for the absolute positions of the smaller ones, whichever works.

Here's some working code for both approaches:

\documentclass[presentation]{beamer}
\usepackage{qtree, tikz}
\usepackage[english]{babel}
\begin{document}

\begin{frame}{\texttt{qtree}}
\Tree
[.\visible<6>{root}
    \visible<6>{\alert<6>{leaf 1}}
    [.\visible<5->{level1node} 
        \visible<5->{\alert<5>{leaf 2}}
        [.\visible<4->{level2node}
            \visible<4->{\alert<4>{leaf 3}}
            [.\visible<3->{level3node}
                \visible<3->{\alert<3>{leaf 4}}
                [.\visible<2->{level4node}
                    \visible<2->{\alert<2>{leaf 5}}
                    [.{level5node}
                        \alert<1>{leaf 6}
                        {leaf 7} 
                    ] 
                ] 
            ] 
        ] 
    ] 
]
\end{frame}

\begin{frame}{overprint version}

This is my tree:
\vskip0pt plus 1filll
\begin{flushright}

\begin{overprint}
\onslide<6>
\Tree
[.{root}
  {\alert<6>{leaf 1}}
  [.{level1node} 
    {\alert<5>{leaf 2}}
    [.{level2node}
        {\alert<4>{leaf 3}}
        [.{level3node}
            {\alert<3>{leaf 4}}
            [.{level4node}
                {\alert<2>{leaf 5}}
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 
            ] 
        ] 
    ] 
  ] 
]

\onslide<5>
\Tree
  [.{level1node} 
    {\alert<5>{leaf 2}}
    [.{level2node}
        {\alert<4>{leaf 3}}
        [.{level3node}
            {\alert<3>{leaf 4}}
            [.{level4node}
                {\alert<2>{leaf 5}}
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 
            ] 
        ] 
    ] 
  ] 

\onslide<4>
\Tree
    [.{level2node}
        {\alert<4>{leaf 3}}
        [.{level3node}
            {\alert<3>{leaf 4}}
            [.{level4node}
                {\alert<2>{leaf 5}}
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 
            ] 
        ] 
    ] 

\onslide<3>
\Tree
        [.{level3node}
            {\alert<3>{leaf 4}}
            [.{level4node}
                {\alert<2>{leaf 5}}
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 
            ] 
        ] 

\onslide<2>
\Tree
            [.{level4node}
                {\alert<2>{leaf 5}}
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 
            ] 

\onslide<1>
\Tree
                [.{level5node}
                    \alert<1>{leaf 6}
                    {leaf 7} 
                ] 

\end{overprint}
\end{flushright}

\end{frame}
\end{document}

Edit:

On the basis of Lay's answer, I managed to create the following branching tikz tree which comes close, but I'm still not quite happy: the edge that connects the currently displayed subtree to the rest of the tree is shown too early - I get a funny tail towards the rest of the tree that doesn't yet exist. If I adapt the position of the tikzstyle-change, the edges are drawn too late:

\begin{frame}
\begin{tikzpicture}
\tikzstyle{lvl0}=[transparent]
\tikzstyle{lvl1}=[transparent]
\tikzstyle{lvl2}=[transparent]
\tikzstyle{lvl3}=[transparent]
\tikzstyle{lvl4}=[transparent]
\tikzstyle{lvl5}=[opaque]
\only<2->{\tikzstyle{lvl4}=[opaque]}
\only<3->{\tikzstyle{lvl3}=[opaque]}
\only<4->{\tikzstyle{lvl2}=[opaque]}
\only<5->{\tikzstyle{lvl1}=[opaque]}
\only<6->{\tikzstyle{lvl0}=[opaque]}
\node [lvl0] {root}
child [lvl0] { node {leaf 1} }
child [lvl1] { node {lvl1}
 child { node [lvl1] {leaf 2} }
 child [lvl2]{ node {lvl2}
  child { node [lvl2] {leaf 3} }
  child [lvl3] { node {lvl3}
    child { node [lvl3] {leaf 4} }
    child { [lvl4] node {lvl4}
      child { node [lvl4] {leaf 5} }
      child { [lvl5] node {lvl5}
        child { node [lvl5] {leaf 6} }
        child { node [lvl5] {leaf 7} }
        }
      }
    }
  }
};
\end{tikzpicture}
\end{frame}
7

Coming from Using beamer overlays with forest generated trees and exploiting the various for … keys, one can achieve your output with only one key dont show before which subsequently sets the appropriate beamer alternatives for other leaves.

This example is rather short (only one sibling, only one big branch) so you might adjust your settings to adapt your use-case.
(Maybe I should have used for first instead of the weird option dont show before=0 which sets alert on=1 for leaf 6 but the dont show before route makes it possible to climb up while highlights new leaves coming from other branches. Incrementing every value that is used with dont show before the first slide only shows leaf 7 and then starts to climb up.)

Code

\documentclass[presentation]{beamer}
\setbeamertemplate{navigation symbols}{}%Remove navigation bar
\usepackage{forest}
\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}}}}
\forestset{
  alert on/.style={
    /tikz/alt=<#1>{node options={/tikz/text=alert}}{}},
  dont show before/.style={
%    for first={alert on=#1},
    for ancestors'={
      /tikz/visible on={<#1->},
      edge={/tikz/visible on={<#1->}}},
    for all previous={
      for tree={
        alert on=\number\numexpr#1+1\relax,
        /tikz/visible on={<\number\numexpr#1+1\relax->},
        edge={/tikz/visible on={<\number\numexpr#1+1\relax->}}
      }},
    for children={edge={/tikz/visible on={<#1->}}}}}
\begin{document}
\begin{frame}{\texttt{forest}}
\begin{forest}
  [root,dont show before=6
    [leaf 1]
    [level1node,dont show before=5
      [leaf 2]
      [level2node,dont show before=4
        [leaf 3]
        [level3node,dont show before=3
          [leaf 4]
          [level4node,dont show before=2
            [leaf 5]
            [level5node,dont show before=1
              [leaf 6]
              [leaf 7,dont show before=0]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{frame}
\end{document}

Output

enter image description here

  • While your code worked perfectly in a minimal file, I initially had trouble compiling in my actual file - until I moved the tikzset/forestset-magic to a different position in the preamble (What I got was TeX capacity exceeded, sorry [parameter stack size=10000]). By try and error, I found that it seems to clashing with gb4e iff following it. Any idea why that might be? – JakobMST May 7 '13 at 7:57
  • 1
    The manual of gb4e states on the first page: “it must be loaded after any file that uses [_ and ^] in their TeX meaning.” The forest package uses _ in names of a few keys. – Qrrbrbirlbel May 7 '13 at 10:27
4

Here's a quick and dirty answer. I'm assuming there must be something more clever, but I like defining tikzstyles within \only<> commands.

\begin{tikzpicture}
  \tikzstyle{lvl0}=[transparent]
  \tikzstyle{lvl1}=[transparent]
  \tikzstyle{lvl2}=[transparent]
  \tikzstyle{lvl3}=[transparent]
  \tikzstyle{lvl4}=[transparent]
  \tikzstyle{lvl5}=[opaque]
  \only<2->{\tikzstyle{lvl4}=[opaque]}
  \only<3->{\tikzstyle{lvl3}=[opaque]}
  \only<4->{\tikzstyle{lvl2}=[opaque]}
  \only<5->{\tikzstyle{lvl1}=[opaque]}
  \only<6->{\tikzstyle{lvl0}=[opaque]}
  \node [lvl0] {root}
  child [lvl0] {
    node [lvl1] {child1}
    child [lvl1]{
      node [lvl2] {child2}
      child [lvl2] {
        node [lvl3] {child3}
        child [lvl3] {
          node [lvl4] {child4}
          child [lvl4] {
            node [lvl5] {child5}
          }
        }
      }
    }
  };
\end{tikzpicture}

I don't know the qtree package, but I am assuming that there must be a way to adapt my example.

Code that matches JakobMST's code from his edit:

\begin{frame}
\begin{tikzpicture}
\tikzstyle{lvl0}=[transparent]
\tikzstyle{lvl1}=[transparent]
\tikzstyle{lvl2}=[transparent]
\tikzstyle{lvl3}=[transparent]
\tikzstyle{lvl4}=[transparent]
\tikzstyle{lvl5}=[transparent]
\tikzstyle{lvl6}=[opaque]
\only<2->{\tikzstyle{lvl5}=[opaque]}
\only<3->{\tikzstyle{lvl4}=[opaque]}
\only<4->{\tikzstyle{lvl3}=[opaque]}
\only<5->{\tikzstyle{lvl2}=[opaque]}
\only<6->{\tikzstyle{lvl1}=[opaque]}
\only<7->{\tikzstyle{lvl0}=[opaque]}
\node [lvl0] {root}
child [lvl0] { 
  node [lvl1] {leaf 1} 
}
child [lvl0] { 
  node {}
  child [lvl1] { 
    node [lvl2] {leaf 2} 
  }
  child [lvl1] { 
    node {}
    child [lvl2] { 
      node [lvl3] {leaf 3} 
    }
    child [lvl2] { 
      node {}
      child [lvl3] { 
        node [lvl4] {leaf 4}
      }
      child [lvl3] { 
        node {}
        child [lvl4] { 
          node [lvl5] {leaf 5} 
        }
        child [lvl4] { 
          node {}
          child [lvl5] { node [lvl6] {leaf 6} }
          child [lvl5] { node [lvl6] {leaf 7} }
        }
      }
    }
  }
};
\end{tikzpicture}
\end{frame}
  • I've edited my post to include a version inspired by your method, but it still doesn't quite do as I wish. Thank you, though! – JakobMST May 7 '13 at 1:33
  • 1
    I've edited my post with a version that, I think, achieves the desired behavior on the example from your edit. You can basically reveal exactly what you want exactly when you want to, with this strategy, so you should be able to make it work if it still does not answer your exact question. Qrrbrbirlbel's answer looks much neater though. – Lay May 7 '13 at 1:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.