20

I want to highlight some portion of my pseudo codes in my slides during the course of presentation. It's easy in powerpoint and I've made a sample slide:

enter image description here

However, I couldn't manage to get a similar effect with beamer, tikz and algorithm2e package.

So far, I've defined the following command.

\newcommand<>{\myspot}[1]
{
\begin{tikzpicture}
        \node[draw=none,inner sep=0cm] (n1)
        {
            #1
        };
    \uncover#2{
        \draw (n1) node[rectangle,inner sep=0cm, fill=yellow] (n2)
        {
            #1
        };
    }
    \end{tikzpicture}
}

It is very useful, but can only highlight a single line in my code.

\myspot<2>{
$pseudo_code here$
}

How can I make a similar effect shown in the sample slide by using beamer?

1 Answer 1

26

Use \tikzmark to place auxiliary nodes and the fit library, together with the remember picture, overlay options to place the shadings. A little example:

\documentclass{beamer}
\usepackage[ruled,vlined,linesnumbered]{algorithm2e}
\usepackage{tikz}
\usetikzlibrary{fit,calc}

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

\definecolor{mybrown}{RGB}{255,218,195}
\definecolor{myframe}{RGB}{197,122,195}

\begin{document}

\begin{frame}

\begin{columns}
\column{.4\textwidth}
\onslide<2->{
\setlength\fboxsep{6pt}%
\framebox{\begin{tikzpicture}[x=0.8cm,init/.style={circle,fill=green!60!black,inner sep=2pt},
tran/.style={circle,fill=magenta!60!black,inner sep=3pt}]
\node<1,2,3>[init] at (0,0) (p) {};
\node<4>[tran] at (0,0) (p) {};
\node[init] at (1,-1) (q) {};
\node[init] at (3,-1) (r) {};
\node<1,2,4>[init] at (2.5,-2) (s) {};
\node<3>[tran] at (2.5,-2) (s) {};
\node[init] at (3.5,-3) (t) {};
\draw[blue] (p) -- (q) -- (r)  -- (s);
\draw[blue] (r) -- (t);
\end{tikzpicture}}
}

\column{.6\textwidth}
\begin{algorithm}[H]
\SetKwData{Left}{left}\SetKwData{This}{this}\SetKwData{Up}{up}
\SetKwFunction{Union}{Union}\SetKwFunction{FindCompress}{Find}
\SetKwInOut{Input}{input}\SetKwInOut{Output}{output}

\For{$i\leftarrow 2$ \KwTo $l$}
{
\emph{special treatment of $i$}\;
\For{$j\leftarrow 2$ \KwTo $w$}{\label{forins}
\Left$\leftarrow$ \FindCompress{$Im[i,j-1]$}\;
\tikzmark{a}\If(\tcp*[h]{}){\Left compatible \This}{\label{lt}
\lIf{\Left $<3$}{\Union{\Left}}\;
\lElse{\Union{\This,\Left}\tikzmark{b}\;}
}
\tikzmark{c}\If(\tcp*[h]{}){\Left compatible \This}{\label{lt1}
\lIf{\Left $<3$}{\Union{\Left}}\;
\lElse{\Union{\This,\Left}\tikzmark{d}\;}
}
}
\lForEach{element $e$ of the line $i$}{\FindCompress{p}}
}
\caption{disjoint decomposition}\label{algo_disjdecomp}
\end{algorithm}
\end{columns}

\begin{tikzpicture}[remember picture,overlay]
\coordinate (aa) at ($(a)+(0,0.2)$);
\coordinate (bb) at ($(b)+(1.2,0)$);
\node<3>[draw=myframe,line width=1pt,fill=mybrown,opacity=0.4,rectangle,rounded corners,fit=(aa) (bb)] {};
\coordinate (cc) at ($(c)+(0,0.2)$);
\coordinate (dd) at ($(d)+(1.2,0)$);
\node<4>[draw=myframe,line width=1pt,fill=mybrown,opacity=0.4,rectangle,rounded corners,fit=(cc) (dd)] {};
\end{tikzpicture}
\end{frame}

\end{document}

The four resulting slides:

enter image description here enter image description here enter image description here enter image description here


Added by Andrew Stacey

Here's a version using the slightly improved tikzmark which makes it possible to put the boxes behind the text. While I was at it, I also added in overlay-aware styles for those two nodes, and non-jumping pictures because the small jump when the node size changes annoyed me (you need to compile the code to see the effect of this, try commenting out the stop jumping key on the tikzpicture environment). I found that \resetcounteronoverlays{algocf} did work - unless I missed something. On the plus side, I got rid of the dependency on the fit and calc libraries. Here's the full code:

\documentclass{beamer}
% \url{https://tex.stackexchange.com/q/51582/86}
%
% Using code from:
%  https://tex.stackexchange.com/a/6155/86 for overlay-aware styles
%  https://tex.stackexchange.com/a/50054/86 for advanced tikzmark
%  https://tex.stackexchange.com/q/18704/86 for the non-jumping pictures
\usepackage[ruled,vlined,linesnumbered]{algorithm2e}
\usepackage{tikz}
\makeatletter

\newcounter{jumping}
\resetcounteronoverlays{jumping}

\def\jump@setbb#1#2#3{%
  \@ifundefined{jump@#1@maxbb}{%
    \expandafter\gdef\csname jump@#1@maxbb\endcsname{#3}%
  }{%
    \csname jump@#1@maxbb\endcsname
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    #3
    \pgfmathsetlength\pgf@x{max(\pgf@x,\pgf@xa)}%
    \pgfmathsetlength\pgf@y{max(\pgf@y,\pgf@ya)}%
    \expandafter\xdef\csname jump@#1@maxbb\endcsname{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
  }
  \@ifundefined{jump@#1@minbb}{%
    \expandafter\gdef\csname jump@#1@minbb\endcsname{#2}%
  }{%
    \csname jump@#1@minbb\endcsname
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    #2
    \pgfmathsetlength\pgf@x{min(\pgf@x,\pgf@xa)}%
    \pgfmathsetlength\pgf@y{min(\pgf@y,\pgf@ya)}%
    \expandafter\xdef\csname jump@#1@minbb\endcsname{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
  }
}

\tikzset{%
  remember picture with id/.style={%
    remember picture,
    overlay,
    save picture id=#1,
  },
  save picture id/.code={%
    \edef\pgf@temp{#1}%
    \immediate\write\pgfutil@auxout{%
      \noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
  },
  if picture id/.code args={#1#2#3}{%
    \@ifundefined{save@pt@#1}{%
      \pgfkeysalso{#3}%
    }{
      \pgfkeysalso{#2}%
    }
  },
  onslide/.code args={<#1>#2}{%
    \only<#1>{\pgfkeysalso{#2}}%
  },
  alt/.code args={<#1>#2#3}{%
    \alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}%
  },
  stop jumping/.style={
    execute at end picture={%
      \stepcounter{jumping}%
      \immediate\write\pgfutil@auxout{%
        \noexpand\jump@setbb{\the\value{jumping}}{\noexpand\pgfpoint{\the\pgf@picminx}{\the\pgf@picminy}}{\noexpand\pgfpoint{\the\pgf@picmaxx}{\the\pgf@picmaxy}}
      },
      \csname jump@\the\value{jumping}@maxbb\endcsname
      \path (\the\pgf@x,\the\pgf@y);
      \csname jump@\the\value{jumping}@minbb\endcsname
      \path (\the\pgf@x,\the\pgf@y);
    },
  }
}


\def\savepointas#1#2{%
  \expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}

\def\tmk@labeldef#1,#2\@nil{%
  \def\tmk@label{#1}%
  \def\tmk@def{#2}%
}

\tikzdeclarecoordinatesystem{pic}{%
  \pgfutil@in@,{#1}%
  \ifpgfutil@in@%
    \tmk@labeldef#1\@nil
  \else
    \tmk@labeldef#1,\pgfpointorigin\@nil
  \fi
  \@ifundefined{save@pt@\tmk@label}{%
    \tikz@scan@one@point\pgfutil@firstofone\tmk@def
  }{%
  \pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
  \pgfsys@getposition{\pgfpictureid}\save@this@pic%
  \pgf@process{\pgfpointorigin\save@this@pic}%
  \pgf@xa=\pgf@x
  \pgf@ya=\pgf@y
  \pgf@process{\pgfpointorigin\save@orig@pic}%
  \advance\pgf@x by -\pgf@xa
  \advance\pgf@y by -\pgf@ya
  }%
}
\newcommand\tikzmark[2][]{%
\tikz[remember picture with id=#2] #1;}
\makeatother

\definecolor{mybrown}{RGB}{255,218,195}
\definecolor{myframe}{RGB}{197,122,195}

\resetcounteronoverlays{algocf}

\newcommand<>{\boxto}[1]{%
\only#2{\tikz[remember picture,overlay]
\draw[myframe,line width=1pt,fill=mybrown,,rectangle,rounded corners]
(pic cs:#1) ++(1.4,-.25) rectangle (-.2,0.4)
;}%
}


\begin{document}

\begin{frame}
\begin{columns}
\column{.4\textwidth}
\onslide<2->{
\setlength\fboxsep{6pt}%
\framebox{\begin{tikzpicture}[
      x=0.8cm,
      init/.style={circle,fill=green!60!black,inner sep=2pt},
      tran/.style={circle,fill=magenta!60!black,inner sep=3pt},
      stop jumping
    ]
\node[alt=<4>{tran}{init}] at (0,0) (p) {};
\node[init] at (1,-1) (q) {};
\node[init] at (3,-1) (r) {};
\node[alt=<3>{tran}{init}] at (2.5,-2) (s) {};
\node[init] at (3.5,-3) (t) {};
\draw[blue] (p) -- (q) -- (r)  -- (s);
\draw[blue] (r) -- (t);
\end{tikzpicture}}
}

\column{.6\textwidth}
\begin{algorithm}[H]
\SetKwData{Left}{left}\SetKwData{This}{this}\SetKwData{Up}{up}
\SetKwFunction{Union}{Union}\SetKwFunction{FindCompress}{Find}
\SetKwInOut{Input}{input}\SetKwInOut{Output}{output}

\For{$i\leftarrow 2$ \KwTo $l$}
{
\emph{special treatment of $i$}\;
\For{$j\leftarrow 2$ \KwTo $w$}{\label{forins}
\Left$\leftarrow$ \FindCompress{$Im[i,j-1]$}\;
\boxto<3>{b}\If(\tcp*[h]{}){\Left compatible \This}{\label{lt}
\lIf{\Left $<3$}{\Union{\Left}}\;
\lElse{\Union{\This,\Left}\tikzmark{b}\;}
}
\boxto<4>{d}\If(\tcp*[h]{}){\Left compatible \This}{\label{lt1}
\lIf{\Left $<3$}{\Union{\Left}}\;
\lElse{\Union{\This,\Left}\tikzmark{d}\;}
}
}
\lForEach{element $e$ of the line $i$}{\FindCompress{p}}
}
\caption{disjoint decomposition}\label{algo_disjdecomp}
\end{algorithm}
\end{columns}

\end{frame}

\end{document}

First slide with highlighted code Second slide with highlighted code Third slide with highlighted code Fourth slide with highlighted code

5
  • Gonzalo, thanks a million. It works perfect. However, there is a minor issue. As you can see in the slides, the "Algorithm number" increases as we put more overlays. Is there a way to keep algorithm number constant? Because, we have just one algorithm. Thanks
    – Octavius
    Commented Apr 11, 2012 at 21:00
  • 3
    Hooray for \tikzmark! Incidentally, if you use the new-and-improved version then you can put the code for the block before the code so that it goes under the text rather than over it. Commented Apr 11, 2012 at 21:05
  • @OktayArslan: yes, sorry for that. Unfortunately the obvious solution \resetcounteronoverlays{algocf} does not work, so you will have to add \setcounter{algocf}{3} right after \begin{frame} (this will show the number 4 for the algorithm). Don't forget to accept (by clicking on the tickmark below the vote count) my answer (or possibly another one) that solves your problem ;-) Commented Apr 11, 2012 at 21:28
  • I just tried \resetcounteronoverlays{algocf} to see what was going wrong and it worked as I expected it to. What went wrong for you, Gonzalo? Commented Apr 12, 2012 at 7:12
  • @AndrewStacey: now I don't know. When I used it testerday, it didn't work as expected, but now I've used it and it worked! I don't know why it didn't work yesterday (who knows where my head was). By the way, great code! Commented Apr 12, 2012 at 21:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .