2

There is something in the manual about avoiding jumps and it is explained here Avoiding jumping frames in beamer as well. But I have maybe a different situation in trees. Is there a way to avoid the jumps between the two figures in the following code?

\documentclass{beamer}

\usepackage{forest}

% http://tex.stackexchange.com/questions/167690/presenting-a-forest-tree-from-bottom-to-top-in-beamer
% showing and hiding nodes and edges in 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}} % \pgfkeysalso doesn't change the path
    },
}
\forestset{
  visible on/.style={
    for tree={
      /tikz/visible on={#1},
      edge={/tikz/visible on={#1}}}}}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\upshape\scshape #1}\right\rangle$}%
}

% specification for all trees, "default preamble" appends to existing specification.
% The version with apostrophe replaces it.
\forestset{default preamble'={
    for tree={align=center,parent anchor=south, child anchor=north,anchor=north,base=bottom},
    before drawing tree={
      sort by=y,
      for min={tree}{baseline}
    }
  }}


\forestset{
  declare dimen={child anchor yshift}{0pt},
  adjust childrens child anchors/.style={
    if n children>=2{
      before packing={
        tempdima/.max={max_y}{children},
        for children={
          child anchor yshift=tempdima()-max_y()
        },
      }
    }{}
  },
  default preamble={
    for tree={
      edge path'={(!u.parent anchor)--([yshift=\forestoption{child anchor yshift}].child anchor)},
      adjust childrens child anchors
    }
  },
}


\begin{document}

\frame{

\begin{forest}
[S
 [\alt<1>{XP}{NP1234}]
 [\alt<1>{YP}{NP1234}]
 [\alt<1>{ZP}{NP1234}]
 [\ldots, visible on=<1>]
 [{\alt<1>{H}{V} \sliste{ \alt<1>{XP}{NP}, \alt<1>{YP}{NP}, \alt<1>{ZP}{NP}\visible<1>{, \ldots} }}
   [{V \sliste{ NP, NP, NP }}, visible on=<1>,no edge]]]
\end{forest}

\pause

}


\end{document}

Edit: Made the NPs longer by adding 1234 so that the jump is really obvious.

Stefan Müller
  • 6,901
  • 3
  • 29
  • 61
  • According to what I find your frame does not jump. Could you please add \begin{tikzpicture}[overlay,remember picture] \draw[red] (current page.west) -- (current page.east); \end{tikzpicture} just before \pause, compile 3 times and tell me if you really see a jump. –  Mar 03 '19 at 17:49
  • Yes, if you hold a piece of paper at NP and check with ZP after advancing to the next slide, you see that ZP starts at a different place from NP. – Stefan Müller Mar 03 '19 at 18:16
  • I just played the thing on full screen mode in acroread and have a hard time confirming what you are saying. Apart from the obvious observation that the characters used in the tree have different widths I cannot see any jump. Please consider clarifying which jumps you are talking about. –  Mar 03 '19 at 18:30
  • It jumps. If you hold a piece of paper at the N of NP that was a ZP on slide 1 you see that the NP does not start at the position of the ZP. Also the tree edges are at different places. – Stefan Müller Mar 03 '19 at 18:42
  • All I can say is that I am unable to reproduce this on my TeXLive 2018 installation when I view the result with acroread. You could use convert -density 300 -delay 4 -loop 0 -alpha remove multipage.pdf animated.gif (see https://tex.stackexchange.com/a/136919/121799) in order to produce an animated gif that you can add to your question. –  Mar 03 '19 at 18:50
  • Did this. (and here some characters to reach the minimum length) – Stefan Müller Mar 03 '19 at 19:39
  • 1
    OK, thanks! Yes, "Apart from the obvious observation that the characters used in the tree have different widths I cannot see any jump. " You could add a minimum width to the nodes whose contents changes. –  Mar 03 '19 at 22:58
  • Yes, I added stuff to the nodes making the NP nodes really wider than the XP/YP/ZP nodes. minimum width works. Thanks! But I have to guess the width. This should be automatic. – Stefan Müller Mar 04 '19 at 07:44

1 Answers1

3

This may be a first step towards a solution. I added a key min width to which can pass the two different texts. Yes, it would be much better if one could change \alt to do that automatically, but I was unable to do this because of expansion issues. (I do not even know against whose expansion I was fighting, beamer or forest.)

\documentclass{beamer}

\usepackage{forest}

% http://tex.stackexchange.com/questions/167690/presenting-a-forest-tree-from-bottom-to-top-in-beamer
% showing and hiding nodes and edges in 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}} % \pgfkeysalso doesn't change the path
    },
}
\forestset{
  visible on/.style={
    for tree={
      /tikz/visible on={#1},
      edge={/tikz/visible on={#1}}}}}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\upshape\scshape #1}\right\rangle$}%
}

% specification for all trees, "default preamble" appends to existing specification.
% The version with apostrophe replaces it.
\forestset{default preamble'={
    for tree={align=center,parent anchor=south, child anchor=north,anchor=north,base=bottom},
    before drawing tree={
      sort by=y,
      for min={tree}{baseline}
    }
  }}


\forestset{
  declare dimen={child anchor yshift}{0pt},
  adjust childrens child anchors/.style={
    if n children>=2{
      before packing={
        tempdima/.max={max_y}{children},
        for children={
          child anchor yshift=tempdima()-max_y()
        },
      }
    }{}
  },
  default preamble={
    for tree={
      edge path'={(!u.parent anchor)--([yshift=\forestoption{child anchor yshift}].child anchor)},
      adjust childrens child anchors
    }
  },
}


\begin{document}
\tikzset{min width/.style n args={2}{/utils/exec={\pgfmathparse{max(width("#1"),width("#2"))}
 \edef\mywidth{\pgfmathresult}},
 text width={\mywidth pt}}}
\frame{

\begin{forest}
[S
 [\alt<1>{XP}{NP1234},min width={XP}{NP1234}]
 [\alt<1>{YP}{NP1234},min width={YP}{NP1234}]
 [\alt<1>{ZP}{NP1234},min width={ZP}{NP1234}]
 [\ldots, visible on=<1>]
 [{\alt<1>{H}{V} \sliste{ \alt<1>{XP}{NP}, \alt<1>{YP}{NP}, \alt<1>{ZP}{NP}\visible<1>{, \ldots} }}
   [{V \sliste{ NP, NP, NP }}, visible on=<1>,no edge]]]
\end{forest}

\begin{tikzpicture}[overlay,remember picture] 
\draw[red] (current page.south west) grid (current page.north east); 
\end{tikzpicture}
\pause

}


\end{document}

enter image description here

The red grid is only to guide the eye.