6

Unrevealing a tree (nodes+edges) has been already treated before e.g.:

Beamer: problematic use of \visible and \only in combination with TikZ to draw a graph

Successively reveal tree bottom up

Step-by-step revealing of tikz-tree using opacity trick and overlays in beamer

However, I am intending something slightly different and I do not know how to adjust previous answers to my case. Here is what I want: I have a simple binary tree with 4 leaf nodes e.g.:

\documentclass{beamer}

\usepackage{tikz}

\tikzset{
  invisible/.style={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
  },
}

\begin{document}

\begin{frame}
  \tikzset{vertex/.style={circle,fill=white!25,minimum size=20pt,inner sep=0pt}}
  \tikzset{leaf/.style={circle,fill=white!25,minimum size=20pt,inner sep=0pt}}
  \tikzstyle{level 1}=[sibling distance=40mm, style={black,very thick,draw}]
  \tikzstyle{level 2}=[sibling distance=20mm, style={black,very thick,draw}]

  \begin{center}
  \begin{tikzpicture}[every node/.style={circle,draw, very thick}]
    \node[vertex,visible on=<3->,  label={[visible on=<3->, yshift=-1.2cm, align=center]above: car, bus, cat, dog}] (1) {}
    child{node[vertex, visible on=<2->, label={[visible on=<2->, yshift=-0.6cm, align=center]above:  car, bus}] (2) {}
      child{node[leaf,visible on=<1->, label={[yshift=0.1cm, align=center]below: car}] (6) {}}
      child{node[leaf, label={[yshift=0.1cm, align=center]below: bus}] (7) {}}
    }
    child {node[vertex, visible on=<2->, label={[visible on=<2->, yshift=-0.67cm, align=center]above: cat, dog}](3) {}
      child{node[leaf, label={[yshift=0.1cm, align=center]below: cat}] (4) {}}
      child{node[leaf, label={[yshift=0.1cm, align=center]below: dog}] (5) {}}
    };
  \end{tikzpicture}
  \end{center}
\end{frame}
\end{document}

I am intending to reveal the nodes and edges starting from the bottom layer. So far, I only managed it for the nodes. But it is unclear to me how to make the edges appear one after another too. Currently, all the edges are rendered. I already experimented with edge from parent[visible on=<2->] but I was not successful.

What am I missing ?

PS: I am a tikz novice.

  • If I understand correct, you like to uncover tree in opposite direction as it grow? Than it will be probably easier to draw figure without `tree˙package in the same order as you like to uncover the picture. – Zarko Oct 20 '15 at 17:46
  • Yes you got it right: I need to uncover it in the opposite direction. – homeless Oct 20 '15 at 17:59
  • If you can adapt your tree to forest, this answer can help you: tex.stackexchange.com/a/167750/1952 – Ignasi Oct 20 '15 at 18:22
  • The second link in the question already points out a solution for forest trees. Unfortunately, the tree is not a forest. – homeless Oct 20 '15 at 18:24
  • If you provide a complete and compilable code, may be we can help you to convert it to forest. – Ignasi Oct 20 '15 at 18:35
5

I originally thought that it would be easy to adapt the code from Qrrbrbirlbel to work with this tree. However, I encountered problems implementing that solution for a tree with the branch pattern in the question.

Based on Qrrbrbirlbel's idea, I developed an alternative approach which makes use of forest's customisation possibilities. These include the ability to define not only new styles, but also new forest options proper. The beauty of this is that, once defined, you can use them just like other forest options. For example, you can use \forestoption{<custom option>} to get the value of your custom option in the context of the current node. And you can apply the various handlers forest supplies as well, although I found I had no need of that here.

We begin with the standard TikZ code for Beamer overlay specifications governing visibility:

\tikzset{% set up for transitions using tikz with beamer overlays
  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
  },
}

Next, we define two forest custom options. These won't actually be needed by the end user in the tree specification, but they will be used internally:

\forestset{%
  declare toks={no node before}{1},
  declare toks={no edge before}{1},

This sets up the options no node before and no edge before with default value of 1 in each case. (So the default is to display everything on every slide.)

Next, we create a forest style for use in the tree specification:

  not before/.style={
    no node before=#1,
    for children={
      no edge before=#1,
    }
  },

This takes a single argument which should be the number of the first slide on which the current node should be shown. It determines the visibility of the current node and of the edges drawn between this node and its children. Unlike Qrrbrbirlbel's dont show before, this does not affect the visibility of siblings or of ancestors. Only the current node and its children's edges are affected.

Finally, we define a style, bottom up which will activate the visibility/invisibility for the tree. It is intended that this should be used in the preamble of the tree so that the effect can be switched on or off as desired without altering the values of not before for the relevant nodes.

  bottom up/.style={% based on Qrrbrbirlbel's answer at https://tex.stackexchange.com/a/112895/
      /tikz/visible on=<\forestoption{no node before}->,
      /tikz/every label/.append style={visible on=<\forestoption{no node before}->},
      /tikz/every edge label/.append style={visible on=<\forestoption{no edge before}->},
      edge={/tikz/visible on=<\forestoption{no edge before}->},
  }

This is an extension of Qrrbrbirlbel's code which ensures that the effect applies not only to nodes and edges, but also to edge labels and labels.

We can then easily specify the tree itself:

  \begin{forest}
    /tikz/every label/.append style={text height=1ex, label distance=5pt},
    for tree={
      circle,
      draw,
      very thick,
      edge={very thick},
      s sep+=10pt,
      fill=white!25,
      minimum size=20pt,
      bottom up,% activate the effect of not before for the tree
    }
    [, label=above:{car, bus, cat, dot}, not before=3% specify visibility
      [, label=above left:{car, bus}, not before=2% specify visibility
        [, label=below:car]
        [, label=below:bus]
      ]
      [, label=above right:{cat, dog}, not before=2% specify visibility
        [, label=below:cat]
        [, label=below:dog]
      ]
    ]
  \end{forest}

Here's the result:

bottom up tree

Complete code:

\documentclass{beamer}
\usepackage{forest}

\tikzset{% set up for transitions using tikz with beamer overlays
  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{%
  declare toks={no node before}{1},
  declare toks={no edge before}{1},
  not before/.style={
    no node before=#1,
    for children={
      no edge before=#1,
    }
  },
  bottom up/.style={% based on Qrrbrbirlbel's answer at https://tex.stackexchange.com/a/112895/
      /tikz/visible on=<\forestoption{no node before}->,
      /tikz/every label/.append style={visible on=<\forestoption{no node before}->},
      /tikz/every edge label/.append style={visible on=<\forestoption{no edge before}->},
      edge={/tikz/visible on=<\forestoption{no edge before}->},
  }
}

\begin{document}
\begin{frame}
  \centering
  \begin{forest}
    /tikz/every label/.append style={text height=1ex, label distance=5pt},
    for tree={
      circle,
      draw,
      very thick,
      edge={very thick},
      s sep+=10pt,
      fill=white!25,
      minimum size=20pt,
      bottom up,
    }
    [, label=above:{car, bus, cat, dot}, not before=3
      [, label=above left:{car, bus}, not before=2
        [, label=below:car]
        [, label=below:bus]
      ]
      [, label=above right:{cat, dog}, not before=2
        [, label=below:cat]
        [, label=below:dog]
      ]
    ]
  \end{forest}
\end{frame}
\end{document}
  • This worked beautifully for me. One follow-up: it doesn't seem to be compatible with forest externalization. Any ideas for combining the two? – Simon C Sep 25 '17 at 14:54
  • 1
    @SimonC No, sorry. I suggest you ask a new question. I typically either avoid overlay specifications for trees in Beamer or disable externalisation for all Forest trees. I'm not sure I've ever successfully combined the two. – cfr Sep 26 '17 at 1:26

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.