6

The following code uncovers a Forest tree level-by-level in a Beamer frame. However, the shadows appear all at once rather than with their nodes. How can I adjust the code so that the shadows stay with the nodes casting them?

\documentclass{beamer}
\usepackage{forest}
\tikzset{% set up for transitions using tikz with beamer overlays - developed by Daniel (http://tex.stackexchange.com/a/55849/) and, in earlier form, by Matthew Leingang (http://tex.stackexchange.com/a/6155/) and modified for this use, I think by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
    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 with edge from/.style={% based on visible on, developed by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
    /tikz/visible on=<#1->,
    /tikz/every label/.append style={visible on=<#1->},
    edge={/tikz/visible on=<#1->},
  },
}
\usetikzlibrary{shadows}
\begin{document}

\begin{frame}
  \begin{forest}
    for tree={
      draw,
      fill=white,
      drop shadow,
    },
    before typesetting nodes={
      for tree={
        tempcounta/.option=level,
        tempcounta'+=1,
        visible with edge from/.register=tempcounta,
      }
    }
    [first slide
      [second slide[third slide][third slide]]
      [second slide]
    ]
  \end{forest}
\end{frame}

\end{document}

Here's the problem:

shadows without nodes

I thought I'd seen code for this, but I can't seem to find a duplicate. In particular, I hope that at least I've not asked this before!

cfr
  • 198,882
  • 1
    cfr is asking a question?! ;) I took the liberty of adding a visualization -- hope that's ok. – Dr. Manuel Kuehner Mar 07 '17 at 19:54
  • 2
    Does this help? I managed to get the opposite invisible/.style={opacity=0,text opacity=0,drop shadow={opacity=0.8,fill=blue}},and comment the drop shadow in the frame (https://www.dropbox.com/s/42p9e420ljd9svx/dsds.gif?dl=0). – Dr. Manuel Kuehner Mar 07 '17 at 20:31
  • 1
    @Dr.ManuelKuehner Thanks. I meant to add an image but had to run for the bus. However, I've now edited. I thought it might be more useful having a picture of the problem rather than one of the only slide which looks fine :-). – cfr Mar 07 '17 at 22:49
  • Going to bed now. I don't understand what you mean with "picture of the problem" since I posted an animated gif. :) – Dr. Manuel Kuehner Mar 07 '17 at 22:51
  • @Dr.ManuelKuehner Oh, I see. Those only work occasionally for me. Or, I guess they only work if you know to look at them right away. I'm afraid I didn't realise. I'm not clear how making the shadows blue would really improve matters, but possibly I'm missing the idea. – cfr Mar 07 '17 at 22:58
  • Making it blue surely doesn't help. My point was, that maybe the opposite of your aim is maybe a spark for creativity. I am not a pro like you guys and I didn't really think that I can seriously help :). It was fun to try :). – Dr. Manuel Kuehner Mar 08 '17 at 05:57
  • 1
    @Dr.ManuelKuehner It is surely my fault for not understanding. – cfr Mar 09 '17 at 00:23

2 Answers2

6

How about this: instead of dealing with \beamer@slideinframe, we trace the opacity of an object and apply that opacity to its shadow. Like the following

\def\tikzshadowopacityregister{1}
\tikzset{
  invisible/.append code={\def\tikzshadowopacityregister{0}},
  every shadow/.style={opacity=\tikzshadowopacityregister}
}

(Put this after \usetikzlibrary{shadows} otherwise every shadow will be erased.)

This strategy is more flexible in the following way: even if someday someone comes up with some \setbeamercovered which sets the opacity in some complicated way, we just need to smuggle the result by a global macro and apply it to the shadow.

PS

My approach above is pretty similar to @Dr. Manuel Kuehner. To save me from plagiarism scandal, here is an even more flexible version

\makeatletter
\def\tikzopacityregister{1}
\tikzset{
  opacity/.append code={
    \pgfmathsetmacro\tikzopacityregister{#1*\tikzopacityregister}
  },
  opacity aux/.code={ % this is the original definition of opacity
    \tikz@addoption{\pgfsetstrokeopacity{#1}\pgfsetfillopacity{#1}}
  },
  every shadow/.style={opacity aux=\tikzopacityregister}
}
Symbol 1
  • 36,855
4

This was suggested to me by the comments, in some round about way that I don't quite understand. That is, it doesn't actually seem related to the suggestion in the comments, which I don't understand and couldn't make work. But I thought of this right after trying to make that work, which suggests a non-trivial connection.

I don't like this solution because it requires an additional style be created for each drop-shadow-like-item and then applied separately from the application of the main overlay specification. This makes it error-prone and I'm good at errors.

However, it does, strictly speaking answer the specific question I asked, so perhaps it will inspire somebody to provide a more satisfactory approach.

\documentclass{beamer}
\usepackage{forest}
\tikzset{% set up for transitions using tikz with beamer overlays - developed by Daniel (http://tex.stackexchange.com/a/55849/) and, in earlier form, by Matthew Leingang (http://tex.stackexchange.com/a/6155/) and modified for this use, I think by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
    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 with edge from/.style={% based on visible on, developed by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
    /tikz/visible on=<#1->,
    /tikz/every label/.append style={visible on=<#1->},
    edge={/tikz/visible on=<#1->},
  },
  drop shadow visible from/.style={/tikz/alt=<#1->{drop shadow}{}},
}
\usetikzlibrary{shadows}
\begin{document}

\begin{frame}
  \begin{forest}
    for tree={
      draw,
      fill=white,
    },
    before typesetting nodes={
      for tree={
        tempcounta/.option=level,
        tempcounta'+=1,
        visible with edge from/.register=tempcounta,
        drop shadow visible from/.register=tempcounta,
      }
    }
    [first slide
      [second slide[third slide][third slide]]
      [second slide]
    ]
  \end{forest}
\end{frame}

\end{document}

shadows with nodes

cfr
  • 198,882