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

I am using the very elegant method from user Daniel described here to try and reveal my tikz-tree gradually. The brief idea is that the tree is always fully drawn to avoid "jumpy" nodes and make their coordinates available even if they are "invisible", but that the opacity is set to 0 on those nodes that are not supposed to be seen yet.

This is how my complete tree should look like after the reveal (I apologize in advance for the miserable quality of my phone's camera):

Here is my code:

\documentclass{beamer}
\usepackage{tikz}
\usepackage[utf8]{inputenc}
\usetikzlibrary{trees}

% Daniel's proposal for "uncovering" parts of a tikz-tree %
\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}
\begin{tikzpicture}[
nor/.style={circle,thick,solid,draw=black,fill=none,inner sep=0.5mm, minimum size=5mm},
acc/.style={circle,thick,solid,draw=green!50!black,fill=green!20,inner sep=0.5mm, minimum size=5mm},
rej/.style={circle,thick,solid,draw=red!50,fill=red!20,inner sep=0.5mm, minimum size=5mm},
level 1/.style={every child/.style={edge from parent/.style={dashed,draw,nearly opaque}} },
level 2/.style={sibling distance=19mm,every child/.style={edge from parent/.style={solid,draw}}},
level 3/.style={sibling distance=8mm,every child/.style={edge from parent/.style={dashed,draw,nearly opaque}} },
semithick]

\node[draw=none] (root) {}
child[level distance=12mm,visible on=<1->] { node[nor] {$x$}
child[visible on=<2->] {node[acc] {$e_1(x)$} }
child[visible on=<2->] {node[nor] {$e_2(x)$}
child[visible on=<6->] child[visible on=<6->] }
child[visible on=<2->] {node[rej] {$e_3(x)$} }
child[visible on=<2->] {node[nor] {$e_4(x)$}
child[visible on=<6->] child[visible on=<6->] child[visible on=<6->] }
};
\end{tikzpicture}
\end{frame}
\end{document}


The 4 sibling nodes on level 2 are correctly hidden, including their solid edges to/from the (x) node. As expected, they show up in the second slide and then stay visible.

But the dashed edges at the bottom of the tree are shown since the very first slide - even though the leaf nodes are set to be visible from slide 6 onwards.

Why is this happening? This way of doing things was accepted as an answer and received a lot of praise in the original question, so it certainly works. It's just partially working for me, since I seem to have a wrong understanding of how child inherits its style to all of the nodes underneath it... or perhaps it's a problem of the levels being styled manually as well (even though this doesn't seem to affect level 2).

Ideas on how to fix this?

-

Preface

Due to MHaaZ comment I tried to investigated what was really wrong with his code and I've found that my orginial answer was not correct enough. I'll leave it here for the records but I prefer to write a new one.

The only problem with your code is using nearly opaque option in level 1 and level 3 style definitions. I still don't understand very well how visible on works but it sets opacity=0 for all invisible pieces and nearly opaque changes this initial value.

I can provide two solutions. First one consist in being sure that visible on option is applied after setting opacity. This way edges or nodes will keep it's opacity when they are visible. Something like

level 1/.style={every child/.style={edge from parent/.style={dashed,draw,nearly opaque, visible on=<2->}}},


will solve the problem (look at original answer code below).

If just want nearly opaque option to fade dashed lines, another solution would be to whiten them. I think dashed, draw=black!30 or similar will have a similar effect and avoid conflicts with visible on. Your code with this second solution will be:

\documentclass{beamer}
\usepackage{tikz}
\usepackage{inputenc}[utf8]
\usetikzlibrary{trees}

% Daniel's proposal for "uncovering" parts of a tikz-tree %
\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}
\begin{tikzpicture}[
nor/.style={circle,thick,solid,draw=black,fill=none,inner sep=0.5mm, minimum size=5mm},
acc/.style={circle,thick,solid,draw=green!50!black,fill=green!20,inner sep=0.5mm, minimum size=5mm},
rej/.style={circle,thick,solid,draw=red!50,fill=red!20,inner sep=0.5mm, minimum size=5mm},
level 1/.style={every child/.style={edge from parent/.style={dashed,draw=black!30}} },
level 2/.style={sibling distance=19mm,every child/.style={edge from parent/.style={solid,draw=black}}},
level 3/.style={sibling distance=8mm,every child/.style={edge from parent/.style={dashed,draw=black!30}} },
semithick]

\node[draw=none] (root) {}
child[level distance=12mm,visible on=<1->] { node[nor] {$x$}
child[visible on=<2->] {node[acc] {$e_1(x)$} }
child[visible on=<2->] {node[nor] {$e_2(x)$}
child[visible on=<6->] child[visible on=<6->] }
child[visible on=<2->] {node[rej] {$e_3(x)$} }
child[visible on=<2->] {node[nor] {$e_4(x)$}
child[visible on=<6->] child[visible on=<6->] child[visible on=<6->] }
};
\end{tikzpicture}
\end{frame}
\end{document}


Last frame will look like:

A node and its corresponding edge from parent can be drawn with different actions, so you can (or have to) apply visible on option to each particular edge. Even applying visible on to a particular level style, you can change it inside a particular node definition.

\documentclass{beamer}
\usepackage{tikz}
\usepackage[utf8]{inputenc}
\usetikzlibrary{trees}

% Daniel's proposal for "uncovering" parts of a tikz-tree %
\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}
\begin{tikzpicture}[
ball/.style={circle, thick, solid,inner sep=0.5mm, minimum size=5mm},
nor/.style={ball,draw=black,fill=none},
acc/.style={ball,draw=green!50!black,fill=green!20},
rej/.style={ball,draw=red!50,fill=red!20},
level 1/.style={every child/.style={edge from parent/.style={dashed,draw,nearly opaque, visible on=<2->}}},
level 2/.style={sibling distance=19mm,every child/.style={edge from parent/.style={solid,draw,visible on=<2->}}},
level 3/.style={sibling distance=8mm,every child/.style={edge from parent/.style={dashed,draw,nearly opaque, visible on=<5->}} },
semithick]

\node[draw=none] (root) {}
child[level distance=12mm,visible on=<1->] { node[nor] {$x$}
child[visible on=<2->] {node[acc] {$e_1(x)$} }
child[visible on=<3->] {node[nor] {$e_2(x)$} edge from parent[red, visible on=<4->]
child[visible on=<6->] child[visible on=<6->] }
child[visible on=<2->] {node[rej] {$e_3(x)$} }
child[visible on=<3->] {node[nor] {$e_4(x)$}
child[visible on=<6->] {} child[visible on=<6->] child[visible on=<6->] }
};
\end{tikzpicture}
\end{frame}
\end{document}


-
Awesome answer, and the animation just tops it off... So, if I understood correctly, the node as well as the corresponding edge from parent are drawn with the options of the child if they are not overriden? This seems sensible, and quite flexible as well... And the problem with my code was that I was styling the edge from parent for level 3 globally, so that I was "overriding" the visible on option from the children on level 3, and thus seeing these edges starting from the first slide? –  MHaaZ Jun 4 '13 at 22:55
@MHaaZ: After looking more carefully to your code, I've found that the problem comes with nearly opaque option. visible on works fixing opacity=0 as starting style, but you overwrite it with nearly opaque. And my code works because I overwrites again with nearly opaque, visible on=<2->. Just change it to visible on=<2->, nearly opaque and it will fail again. I was lucky! –  Ignasi Jun 6 '13 at 8:47
Exactly, that's what I meant in my previous comment: I was styling the whole level correctly, but overwriting the opacity=0 for the edges because nearly opaque is an opacity option. Still, your answer works, and the trick is to always write the visible on=<?> at last, so that it makes everything invisble when it should, and doesn't affect it otherwise. –  MHaaZ Jun 8 '13 at 10:51