7

In the following MWE I want to create a TikZ callout pointing to a node within a node. The outer node is for the highlighting environment \tikzMe the inner node is for the \tikzmark. Somehow I do not achieve that the callout is displayed correctly. Is there a solution?

\documentclass{beamer}
\usepackage{beamerthemeshadow}
\usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{%
shapes.callouts,
shadows
}
\usepackage{xparse}

\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
    },
    BeamerAlert/.style={alt={#1{fill=red!30,rounded corners}{}},anchor=base,inner sep=1pt}
  }

\newcommand<>{\tikzMe}[1]{%
        \tikz[baseline]\node[BeamerAlert={#2},anchor=base,text width=9cm] {#1};      
}

\NewDocumentCommand{\mycallout}{r<> m m m m m m}{%
\tikz[remember picture, overlay]\node[drop shadow, rounded corners, align=left, fill=#7!30, text width=#4,visible on=<#1>,
draw,rectangle callout,anchor=pointer,callout relative pointer={(#5:#6cm)}]
at (#2) {#3};
}

\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=-0.5ex] \node (#1) {};}

\begin{document}

\begin{frame}
\begin{itemize}
  \item Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices.
  \item \tikzMe<2>{Nam arcu libero, nonummy \tikzmark{x}eget, consectetuer id, \dots}
\end{itemize}
\end{frame}

\mycallout<3>{x.north}{Hahahahaha!!!}{5cm}{260}{0.7}{red}

\end{document}

NB: This question combines the accepted answers of Explanatory bubbles in beamer and Highlighting in Beamer using TikZ nodes.

lpdbw
  • 8,330

1 Answers1

7

Notes:

  1. You can define \mycallout with \newcommand<>; I don’t think that xparse is beamer-aware.
  2. the actual use of \mycallout is not inside a frame.
  3. Correcting those two thing, you will still get a shadow of the callout that is not hidden on slides 1 and 2.
    • Approach 1: alt={#7{drop shadow}{invisible}}
    • Approach 2: \node#7[…

Code 1

\documentclass{beamer}
\usepackage{beamerthemeshadow}
\usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts,shadows}

\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
    },
    BeamerAlert/.style={alt={#1{fill=red!30,rounded corners}{}},anchor=base,inner sep=1pt}
  }

\newcommand<>{\tikzMe}[1]{%
        \tikz[baseline]
            \node[BeamerAlert={#2},anchor=base,text width=9cm] {#1};%
}

\newcommand<>{\mycallout}[6]{%
    \tikz[remember picture, overlay]
    \node[
        rounded corners,
        align=left,
        fill=#6!30,
        text width=#3,
        alt={#7{drop shadow}{invisible}},
        draw,
        rectangle callout,
        anchor=pointer,
        callout relative pointer={(#4:#5cm)}
    ] at (#1) {#2};
}

\newcommand{\tikzmark}[1]{%
    \tikz[overlay,remember picture,baseline=-0.5ex]
        \node (#1) {};%
}

\begin{document}

\begin{frame}
\begin{itemize}
  \item Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices.
  \item \tikzMe<2>{Nam arcu libero, nonummy \tikzmark{x}eget, consectetuer id, \dots}
\end{itemize}
\mycallout<3>{x.north}{Hahahahaha!!!}{5cm}{260}{0.7}{red}
\end{frame}
\end{document}

Code 2

This code implements Andrew Stacey's remark. The overlay specification is used at \node#7[….

\documentclass{beamer}
\usepackage{beamerthemeshadow}
\usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts,shadows}

\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
    },
    BeamerAlert/.style={alt={#1{fill=red!30,rounded corners}{}},anchor=base,inner sep=1pt}
  }

\newcommand<>{\tikzMe}[1]{%
        \tikz[baseline]
            \node[BeamerAlert={#2},anchor=base,text width=9cm] {#1};%
}

\newcommand<>{\mycallout}[6]{%
    \tikz[remember picture, overlay]
    \node#7[
        drop shadow,
        rounded corners,
        align=left,
        fill=#6!30,
        text width=#3,
        draw,
        rectangle callout,
        anchor=pointer,
        callout relative pointer={(#4:#5cm)}
    ] at (#1) {#2};
}

\newcommand{\tikzmark}[1]{%
    \tikz[overlay,remember picture,baseline=-0.5ex]
        \node(#1) {};%
}

\begin{document}

\begin{frame}
\begin{itemize}
  \item Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices.
  \item \tikzMe<2>{Nam arcu libero, nonummy \tikzmark{x}eget, consectetuer id, \dots}
\end{itemize}
\mycallout<3>{x.north}{Hahahahaha!!!}{5cm}{260}{0.7}{red}
\end{frame}
\end{document}
Qrrbrbirlbel
  • 119,821
  • To correct for the shadow, put the overlay specification on the \node command rather than using the visible on style. This is needed because the drop shadow invokes a separate drawing command and so also needs to be made overlay aware (it doesn't inherit the visible on). The simplest way to do this is to make the whole thing inside an overlay-aware command. – Andrew Stacey Dec 02 '12 at 17:38
  • @AndrewStacey I actually put drop shadow in the first argument of the alt key (without using visible on). And as the callout is overlayed anyway we could put the whole node specification in the alt key. But your approach is even better. – Qrrbrbirlbel Dec 02 '12 at 17:42
  • 1
    Sorry - I hadn't run your code, just the code from the question and I thought your point 3 referred to some effect that you were still seeing. There are lots of ways to make TikZ things overlay aware and the best choice often depends on other factors so it's good to know all the different ways. – Andrew Stacey Dec 02 '12 at 17:46
  • @AndrewStacey Yeah, no need to be sorry, I was unclear on that point as I had only converted my previous comment. And I do agree, the solution doesn't exist. In this case, though, I think that making \node overlay aware is the straightest approach. – Qrrbrbirlbel Dec 02 '12 at 17:53
  • @Qrrbrbirlbel: yes, xparse is not overlay-aware, but it doesn't matter actually. It depends on how one defines things: in my original code I passed to the style visible on the first argument defined with <> delimiters from xparse. I think in this case is just matter of taste. BTW: one could also solve the problem of shadow visibility in this way: drop shadow={visible on=<...>}. – Claudio Fiandrino Dec 02 '12 at 18:11
  • @Qrrbrbirlbel I am still experimenting with your code 2. I made the following adaptations BeamerAlert/.style={alt={#1{rounded corners}{}},anchor=base,inner sep=1pt}, \node[BeamerAlert={#2},fill=#3!20,anchor=base,text width=9cm] {#1}; That is, I wanted to achieve that the colour of \TikzMe is no longer fixed but can be specified as an argument. But I get an error message with these adaptations. What's the mistake?? – lpdbw Dec 03 '12 at 17:35
  • Ah, \node[BeamerAlert={#3},fill=#2!20,anchor=base,text width=9cm] {#1}; seems to work ... apparently the BeamerAlertargument has to be the last oen ... HHmm, actually I am not really understanding anything but just doing "trial and error" :-( – lpdbw Dec 03 '12 at 18:02
  • @lpdbw Yes, when the overlay specification is created with \newcommand<> it is saved in the last parameter (actually it is the last and then one, i.e. in \newcommand<>{\overlayMe}[4]{…} the overlay specification is saved in #5). – Qrrbrbirlbel Dec 05 '12 at 22:15