4

This is a follow-up question of this one.

In the previous question, I asked how to create an interactive slide with two parts: one left-hand-side part and one right-hand-side part; typically concentrating on the left-hand-side part.

Now, I need help for the right-hand-side part. Consider, as an example:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows}
\tikzstyle{int}=[draw, fill=blue!20, minimum size=2em]
\tikzstyle{init} = [pin edge={to-,thin,black}]

    \begin{document}
    \begin{frame}
    \begin{minipage}{0.2\textwidth}
    \begin{enumerate}
    \item this is 1
    \item this is 2
    \end{enumerate}
    \end{minipage}
    \hfill
    \begin{minipage}{0.75\textwidth}
    \only<1> {

    \begin{tikzpicture}[node distance=2.5cm,auto,>=latex']
        \node [int, pin={[init]above:$v_0$}] (a) {$\frac{1}{s}$};
        \node (b) [left of=a,node distance=2cm, coordinate] {a};
        \node [int, pin={[init]above:$p_0$}] (c) [right of=a] {$\frac{1}{s}$};
        \node [coordinate] (end) [right of=c, node distance=2cm]{};
        \path[->] (b) edge node {$a$} (a);
        \path[->] (a) edge node {$v$} (c);
    \end{tikzpicture}}
    \only<2> {
    \begin{tikzpicture}[node distance=2.5cm,auto,>=latex']
        \node [int, pin={[init]above:$v_0$}] (a) {$\frac{1}{s}$};
        \node (b) [left of=a,node distance=2cm, coordinate] {a};
        \node [int, pin={[init]above:$p_0$}] (c) [right of=a] {$\frac{1}{s}$};
        \node [coordinate] (end) [right of=c, node distance=2cm]{};
        \path[->] (b) edge node {$a$} (a);
        \path[->] (a) edge node {$v$} (c);
        \draw[->] (c) edge node {$p$} (end) ;
    \end{tikzpicture}}
    \end{minipage}
    \end{frame}

    \end{document}

Disclaimer: image sources are shamelessly copied from here.

As you will obviously notice, excepting a small change in the second tikzpicture, the same code is copied. How can I avoid this? In the previous question, I solved this using two separate files and including the images. But aren't there some cute ways?

hola
  • 4,026
  • 3
  • 35
  • 72

1 Answers1

5

An option to avoid code duplication is to use the very useful visible on style defined in this answer to Mindmap tikzpicture in beamer (reveal step by step); also, take into account that paths in TikZ are overlay-aware so this might also help you avoid repeating code unnecessarily or using "external" overlay specifications:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning}

\tikzset{
  int/.style={
    draw, 
    fill=blue!20, 
    minimum size=2em
  },  
  init/.style={pin edge={to-,thin,black}}
}

\tikzset{
  % use option [visible on=<+->] to uncover parts of a tikzpicture
  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{minipage}{0.2\textwidth}
    \begin{enumerate}
    \item this is 1
    \item this is 2
    \end{enumerate}
    \end{minipage}
    \hfill
    \begin{minipage}{0.75\textwidth}
    \begin{tikzpicture}[node distance=1.5cm,auto,>=latex']
        \node [int, pin={[init]above:$v_0$}] (a) {$\frac{1}{s}$};
        \node (b) [left = of a,coordinate] {a};
        \node [int, pin={[init]above:$p_0$}] (c) [right =of a] {$\frac{1}{s}$};
        \node [coordinate] (end) [right = of c]{};
        \path[->] (b) edge node {$a$} (a);
        \path[->] (a) edge node {$v$} (c);
        \draw[->,visible on=<2>] (c) edge node {$p$} (end) ;
    \end{tikzpicture}
    \end{minipage}
    \end{frame}

    \end{document}

enter image description here

The styles are also part of the aobs-tikz package.

I changed the original code to use \tikzset and the =of syntax (with the positioning library) instead of the problematic of= syntax.

Here's the code, combining the solutions to both questions:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,tikzmark}

\newcounter{tmp}
\newcommand<>\Highlight[1]{%
  \stepcounter{tmp}%
  \only#2{%
    \begin{tikzpicture}[remember picture,overlay]
      \fill[green!60!black,opacity=0.5] 
      ([xshift=-.2em,yshift=2ex]pic cs:start-\thetmp)
        rectangle  
      ([xshift=.2em,yshift=-1ex]pic cs:end-\thetmp);
    \end{tikzpicture}}%
  \tikzmark{start-\thetmp}#1\tikzmark{end-\thetmp}%
}

\tikzset{
  int/.style={
    draw, 
    fill=blue!20, 
    minimum size=2em
  },  
  init/.style={pin edge={to-,thin,black}}
}

\tikzset{
  % use option [visible on=<+->] to uncover parts of a tikzpicture
  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{minipage}{0.2\textwidth}
\begin{enumerate}
\item \Highlight<+>{this is 1}
\item \Highlight<+>{this is 2}
\end{enumerate}
\end{minipage}
\hfill
\begin{minipage}{0.75\textwidth}
\begin{tikzpicture}[node distance=1.5cm,auto,>=latex']
    \node [int, pin={[init]above:$v_0$}] (a) {$\frac{1}{s}$};
    \node (b) [left = of a,coordinate] {a};
    \node [int, pin={[init]above:$p_0$}] (c) [right =of a] {$\frac{1}{s}$};
    \node [coordinate] (end) [right = of c]{};
    \path[->] (b) edge node {$a$} (a);
    \path[->] (a) edge node {$v$} (c);
    \draw[->,visible on=<2>] (c) edge node {$p$} (end) ;
\end{tikzpicture}
\end{minipage}
\end{frame}

\end{document}

enter image description here

Gonzalo Medina
  • 505,128