[Tex/LaTex] Using beamer overlays with forest generated trees

beamerforesttikz-pgftikz-treestrees

I am using the forest package from Sašo Živanović in order to create a wide tree on a beamer slide.

Previously, I was using qtree. But due to the easier way of arranging nodes automatically with avoiding overlaps, I have switched to forest. However, with qtree I was able to manage overlays by a macro I have found in Mindmap tikzpicture in beamer (reveal step by step)
with

\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
      },
    }

This is sadly not working for the forest package. It does remove TikZ node attitudes (such as a drawn ellipse around a tree node) but the node text is visible in all slides as well as the subtrees and edges.

So is there a way to use beamer overlays with the forest package in order to partially make subtrees of a tree visible step by step with an animation?

EDIT

Ok here is a MWE for my different cases.

Note, that using TikZ is the result I would like to have with the forest package as well. In my code, the tree has a much bigger depth and playing along with sibling distance and left parameter isn't much fun, so I decided to use forest which auto formats the nodes.

\documentclass[english, ucs, xcolor={table, dvipsnames}]{beamer}

\usepackage[english, ngerman]{babel}

\usepackage{tikz}
\usetikzlibrary{shapes}

% Different tree drawing packages
\usepackage{qtree}
\usepackage{forest}

\setbeamertemplate{navigation symbols}{} %Remove navigation bar


% Being able to set beamer visibility for child nodes in a tree graph
% Daniel's code:
% https://tex.stackexchange.com/questions/55806/tikzpicture-in-beamer/55827#55827
% Use with child [color=.., visible on=<1->]
\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}

% tikz
\begin{frame}{tikz}
    \begin{tikzpicture}\scriptsize
        \tikzset{every node/.style={draw,ellipse}, sibling distance=40mm}

        \node {Picture root}
          child{node[fill=yellow]{First level class}
            child[visible on=<2->]{node[fill=gray]{subcategorized}}
            child[visible on=<2->]{node{another subcategory}
              child{node[fill=gray]{last node division}}
              child{node[fill=gray]{in two classes}}
            }
          }
          child {node[fill=gray]{Another long category}};
    \end{tikzpicture}
\end{frame}



% forest
\begin{frame}[plain]{Same with forest}
    \begin{forest} baseline, for tree={draw,ellipse,align=center}
        [Picture root
            [First level class,fill=yellow
                [subcategorized,fill=gray,visible on=<2->]
                [another subcategory,visible on=<2->
                    [last node division,fill=gray]
                    [in two classes,fill=gray] 
                ] 
            ]
            [Another long category,fill=gray]
        ]    
    \end{forest}
\end{frame}


% And qtree
\begin{frame}{And qtree}
    \begin{tikzpicture}[sibling distance=100mm, every node/.style={draw,ellipse}]
        \Tree [.\node{Picture root};
                [.\node{First level class};\onslide<2->
                    [.\node{subcategorized}; ]
                    [.\node{another subcategory}; 
                        [.\node{last node division}; ]
                        [.\node{in two classes}; ]
                    ]
                ]
                [.\onslide<1->\node{Another long category}; ]
            ]
    \end{tikzpicture}
\end{frame}

\end{document}

The following result is produced:

TikZ standard, forest and qtree

Best Answer

I defined a /forest/visible on option that passes its argument to

  • /tikz/visible on to affect the actual node,
  • and /forest/edge (this is the reason we need a visible on option in the /forest tree).

I asume you also want all following children (and their edges) to be invisible that's why we actually use for tree (meaning the subtree).

Other useful options are for children, for descendants, …; see section 3.3.6 Propagators of the forest manual for reference.

In this example we can use the /forest style visible on in a for children option of the parent node of subcategorized and another subcategory. (You may re-define/add various styles so that you can hide

  • only the current node (and its edges),
  • only the children of the current node (and their edges), and
  • the current node and its children (and its and/or their edges).

Code

\documentclass[xcolor={table, dvipsnames}]{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 tree={
      /tikz/visible on={#1},
      edge+={/tikz/visible on={#1}}}}}
\begin{document}
\begin{frame}[plain]{Same with forest}
    \begin{forest} baseline, for tree={draw,ellipse,align=center}
        [Picture root
            [First level class,fill=yellow,for children={visible on=<2->}
                [subcategorized,fill=gray]
                [another subcategory
                    [last node division,fill=gray]
                    [in two classes,fill=gray] 
                ] 
            ]
            [Another long category,fill=gray]
        ]    
    \end{forest}
\end{frame}
\end{document}

Output

enter image description here