Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to use the soul package to get highlighting via \hl{some text}. I'd like to do this in overlays in beamer. I'm trying to follow the guidelines in section 9.6.1 of the beamer manual to make the \hl command overlay aware. What i'm using is

\renewcommand<>{\hl}[1]{\only#2{\beameroriginal{\hl}}{#1}}

That setup sorta/kinda works, but not exactly.

  • The \hl command is overlay-aware in xelatex, but not in pdflatex or lualatex. I generally use lualatex, so that would be my preference. (Peter Grill has addressed this part in the first half of his answer)
  • The overlays tend to reflow the text a bit, in a way that makes the highlighted text jump around from slide to slide in an awkward manner. You'll see that if you run the example below through xelatex. (Actually, you'll see it in all the engines, but only with the highlights in xelatex). (Peter addressed this in the TikZ part of his answer)

I've attached an MWE of the problem, which I'm sure is some simple ignorance on my part, but I can't seem to resolve.

\documentclass[presentation]{beamer}

\usepackage{xcolor,soul}
\definecolor{lightblue}{rgb}{.90,.95,1}
\sethlcolor{lightblue}
\renewcommand<>{\hl}[1]{\only#2{\beameroriginal{\hl}}{#1}}

\begin{document}
\begin{frame} {Some possibly highlighted text}

This is some normal text

\hl<2>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide}

\hl<3>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide.  This is a long one, so it should
be more than one line}

This is some normal text
\end{frame}
\end{document}
share|improve this question
    
Welcome to TeX.SE. What is #2 in the \renewcommand? \hl only takes on parameter? Oh, wait perhaps this is one of those beamer things I don't know about. –  Peter Grill Oct 3 '12 at 6:04
    
The #2 is the argument to specify the overlay, like <2> to specify the second slide, or <2-> to specify from the second slide until the end of the frame. The overlay-aware versions of commands in beamer can take such an extra argument –  GTK Oct 3 '12 at 6:17
1  
Yep, realized it was something like that once I saw the <> syntax. Don't really have much experience with beamer so thanks for teaching me something. –  Peter Grill Oct 3 '12 at 6:20
add comment

1 Answer

up vote 9 down vote accepted

Using soul package:

Looks like the problem is that beamer redefines things. Using the patch from Why is it that coloring in soul in beamer is not visible seems to work:

enter image description here

Using tikz package:

As Andrew Stacey mentioned int he comments, there is a tikzmark solution as well. Using the code from How to "highlight" text/formals with tikz?, we get:

enter image description here

Notes:

  • Using this solution, the text is identical across the frames.
  • This required a slight tweak from the code at How to "highlight" text/formals with tikz?. The highlighter width was increased form 12pt:

    highlighter width/.initial=14pt
    

    Without this there was additional spacing in between the highlighted lines of the second paragraph.

  • This does require two runs. First one to determine the locations, and the second to do the drawing.

  • The \tikzmark is from Adding a large brace next to a body of text.

Further Enhancements:


Code (soul):

\documentclass[presentation]{beamer}

\usepackage{xcolor,soul}
\definecolor{lightblue}{rgb}{.90,.95,1}
\sethlcolor{lightblue}
\renewcommand<>{\hl}[1]{\only#2{\beameroriginal{\hl}}{#1}}

% http://tex.stackexchange.com/questions/41683/why-is-it-that-coloring-in-soul-in-beamer-is-not-visible
\makeatletter
\newcommand\SoulColor{%
  \let\set@color\beamerorig@set@color
  \let\reset@color\beamerorig@reset@color}
\makeatother
\SoulColor

\begin{document}
\begin{frame} {Some possibly highlighted text}

This is some normal text

\hl<2>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide}

\hl<3>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide.  This is a long one, so it should
be more than one line}

This is some normal text
\end{frame}
\end{document}

Code (tikz):

\documentclass[presentation]{beamer}
\usepackage{xcolor}

%  http://tex.stackexchange.com/questions/46434/how-to-highlight-text-formals-with-tikz
\usepackage{tikz}
\makeatletter
%
% Highlighter code
%

\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}}%
  }
}

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

\tikzdeclarecoordinatesystem{pic}{%
  \@ifundefined{save@pt@#1}{%
    \pgfpointorigin
  }{%
  \pgfsys@getposition{\csname save@pt@#1\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
  }%
}

\newcounter{highlight}
\newcommand{\hlstart}{\tikz[remember picture with id=hlstart\the\value{highlight},baseline=-0.7ex];\hl@start}
\newcommand{\hlend}{\tikz[remember picture with id=hlend\the\value{highlight},baseline=-0.7ex];\hl@end\stepcounter{highlight}}
\newcommand{\fdstart}{\tikz[remember picture with id=hlstart\the\value{highlight},baseline=-0.7ex];\fd@start}
\newcommand{\fdend}{\tikz[remember picture with id=hlend\the\value{highlight},baseline=-0.7ex];\fd@end\stepcounter{highlight}}
\newcommand{\vlstart}{\tikz[remember picture with id=hlstart\the\value{highlight},baseline=-1em];\vl@start}
\newcommand{\vlend}{\tikz[remember picture with id=hlend\the\value{highlight},baseline=0.3ex];\vl@end\stepcounter{highlight}}

\newcommand{\hl@start}[1][]{%
  \hl@draw{highlighter}{#1}{\the\value{highlight}}}

\newcommand{\hl@end}{}

\newcommand{\fd@start}[1][]{%
  \def\fd@args{#1}}

\newcommand{\fd@end}{\def\@tempa{\hl@draw{fader}}\expandafter\@tempa\expandafter{\fd@args}{\the\value{highlight}}\def\fd@args{}}

\newcommand{\vl@start}[1][]{%
  \vl@draw{highlighter}{#1}{\the\value{highlight}}}

\newcommand{\vl@end}{}


\def\hl@sets{%
  \edef\hl@sx{\the\pgf@x}%
  \edef\hl@sy{\the\pgf@y}%
}
\def\hl@sete{%
  \edef\hl@ex{\the\pgf@x}%
  \edef\hl@ey{\the\pgf@y}%
}

\@ifclassloaded{beamer}{

\def\page@node{
  \path (current page.south east)
      ++(-\beamer@rightmargin,\footheight)
  node[
    minimum width=\textwidth,
    minimum height=\textheight,
    anchor=south east
  ] (page) {};
}

}{

  \def\page@node{
    \path (current page.north west)
    ++(\hoffset + 1in + \oddsidemargin + \leftskip,\voffset + 1in + \topmargin + \headheight + \headsep)
    node[
      minimum width=\textwidth - \leftskip - \rightskip,
      minimum height=\textheight,
      anchor=north west
    ] (page) {};
  }

}

\newcommand{\hl@draw}[3]{%
  \begin{tikzpicture}[remember picture,overlay]%
  \page@node
  \tikzset{#2,highlight=#1,every path/.append style={highlight=#1}}%
  \pgfmathsetlengthmacro{\hl@width}{\the\pgflinewidth - 1pt}%
  \coordinate (hlstart) at (pic cs:hlstart#3);
  \coordinate (hlend) at (pic cs:hlend#3);
  \tikz@scan@one@point\hl@sets(pic cs:hlstart#3)
  \tikz@scan@one@point\hl@sete(pic cs:hlend#3)
  \ifdim\hl@sy=\hl@ey\relax
  \draw (hlstart) -- (hlend);
  \else
  \draw (hlstart) -- (hlstart -| page.east);
  \pgfmathsetlengthmacro{\hl@sy}{\hl@sy -\hl@width}%
  \pgfmathsetlengthmacro{\hl@ey}{\hl@ey +\hl@width}%
  \loop\ifdim\hl@sy>\hl@ey\relax
  \draw (0,\hl@sy -| page.west) -- (0,\hl@sy -| page.east);
  \pgfmathsetlengthmacro{\hl@sy}{\hl@sy -\hl@width}%
  \repeat
  \draw (hlend -| page.west) -- (hlend);
  \fi
  \end{tikzpicture}%
}

\newcommand{\vl@draw}[3]{%
  \begin{tikzpicture}[remember picture,overlay]%
  \page@node
  \tikzset{#2,highlight=#1,every path/.append style={highlight=#1}}%
  \pgfmathsetlengthmacro{\hl@width}{\the\pgflinewidth - 1pt}%
  \coordinate (hlstart) at (pic cs:hlstart#3);
  \coordinate (hlend) at (pic cs:hlend#3);
  \tikz@scan@one@point\hl@sets(pic cs:hlstart#3)
  \tikz@scan@one@point\hl@sete(pic cs:hlend#3)
  \ifdim\hl@sx=\hl@ex\relax
  \draw (hlstart) -- (hlend);
  \else
  \draw (hlstart) -- (hlstart |- page.south);
  \pgfmathsetlengthmacro{\hl@sx}{\hl@sx -\hl@width}%
  \pgfmathsetlengthmacro{\hl@ex}{\hl@ex +\hl@width}%
  \loop\ifdim\hl@sx>\hl@ex\relax
  \draw (\hl@sx,0 |- page.north) -- (\hl@sx,0 |- page.south);
  \pgfmathsetlengthmacro{\hl@sx}{\hl@sx -\hl@width}%
  \repeat
  \draw (hlend |- page.north) -- (hlend);
  \fi
  \end{tikzpicture}%
}

\tikzset{%
  highlight/.default=highlighter,
  highlight/.style={
    color=\pgfkeysvalueof{/tikz/#1 colour},
    line width=\pgfkeysvalueof{/tikz/#1 width},
    line cap=\pgfkeysvalueof{/tikz/#1 cap},
    opacity=\pgfkeysvalueof{/tikz/#1 opacity},
  },
  highlighter colour/.initial=yellow,
  highlighter width/.initial=14pt,% <-- Tweak (was 12pt)
  highlighter cap/.initial=butt,
  highlighter opacity/.initial=1,
  fader colour/.initial=gray,
  fader width/.initial=12pt,
  fader cap/.initial=butt,
  fader opacity/.initial=.5,
}



\@ifclassloaded{beamer}{

%% Beamer variants

\setbeamercolor{highlighted text}{bg=yellow}
\setbeamercolor{faded text}{fg=gray}

\newcommand<>{\highlight}[2][]{%
  \only#3{\hlstart[#1]}#2\only#3{\hlend}}

\newcommand<>{\fade}[2][]{%
  \only#3{\fdstart[#1]}#2\only#3{\fdend}}

\newcommand<>{\vhighlight}[2][]{%
  \only#3{\vlstart[#1]}#2\only#3{\vlend}}

}{

\newcommand{\highlight}[2][]{%
\hlstart[#1]#2\hlend}

\newcommand{\fade}[2][]{%
\fdstart[#1]#2\fdend}

\newcommand{\vhighlight}[2][]{%
\vlstart[#1]#2\vlend}

}


\begin{document}
\begin{frame} {Some possibly highlighted text}

This is some normal text

\highlight<2>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide}

\highlight<3>{I'd like this text to appear on both slides, but only be
  highlighted from the second slide.  This is a long one, so it should
be more than one line}

This is some normal text
\end{frame}
\end{document}
share|improve this answer
    
Peter, that solves the problem of using pdflatex or lualatex. Thanks! Now just left with the problem of changes in text layout through the overlays. –  GTK Oct 3 '12 at 6:21
1  
Sorry to have put you back to real work again. :-) –  Peter Grill Oct 3 '12 at 6:25
    
Thanks for posting the output as well. You can see (between slides 2 and 3) the reformatting that gets dragged along with the highlight overlay, at least the way I've done the \renewcommand for \hl. The line third from the bottom ends "should be more" in one slide and "should be more than" when highlighted. –  GTK Oct 3 '12 at 6:37
    
@GTK: Hmmm... I am not sure what is the cause of that. –  Peter Grill Oct 3 '12 at 6:54
1  
What no tikzmark? –  Andrew Stacey Oct 3 '12 at 9:31
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.