2

This problem originates from the idea that I wanted to put spotlight highlighting directly on my slides. I was able to code something like that. (And there is also an alternative here: beamer: using a spotlight to highlight a part of an image .) But the problem is that both approaches hardcode the position where the highlighting position is.

So I wondered if there is a way to determine the position (and size) of text on my slides, to automate this highlighting process. (I.e. writing something like \spotlight{Highlights!} to highlight the text in my example.)

My dream would be a box-style highlight as shown below:

enter image description here

\documentclass[xcolor=dvipsnames]{beamer}
\usetheme{metropolis}
\metroset{block=fill}

\usepackage{tikz} \begin{document} % invclip from: https://tex.stackexchange.com/questions/12010/how-can-i-invert-a-clip-selection-within-tikz \tikzset{invclip/.style={clip,insert path={{[reset cm] (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt) }}}}

\begin{frame}{Example Slide}
    %highlighting overlay
    \begin{tikzpicture}[remember picture,overlay]
    \begin{scope}
    \begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
    \path[invclip]
    % TODO: automatically position, resize this ugly hardcoded box
    (3,-4.95) -- (5.1,-4.95) -- (5.1,-4) -- (3,-4) -- (3,-4.95);
    \end{pgfinterruptboundingbox} 

    \fill[black, opacity=0.5] (current page.south west) rectangle (current page.north east);
    \end{scope}

    \end{tikzpicture}

    % Some (arbitrary) content of the slide.
    Some text here.

    \vspace{3em}

    \hspace{17em} Other text here.

    \vspace{3.2em}

    \hspace{8em} Highlights!
\end{frame}

\end{document}

I don't know how realistic this is, so an alternative could be to manually set the radius of the highlight but still automatically determine the position for it. (Even if the code would be something like Highli\spotlight{2}ghts!.)

Circle

Exchange the pgfinterruptboundingbox environment in the code above with:

\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
    \draw[draw=none, invclip]
    % TODO: automatically reposition this hardcoded circle.
    (4,-4.55) circle (1.6);
\end{pgfinterruptboundingbox} 
plauer
  • 438

1 Answers1

1

Since TeXnician hinted to use the tikzmark package, I was able to solve this problem with it.

We can simply retrieve the position of the text via tikzmark and calculate width/height via saveboxes as follows:

\documentclass[xcolor=dvipsnames]{beamer}
\usetheme{metropolis}
\metroset{block=fill}

\usepackage{tikz} \usetikzlibrary{tikzmark}

% invclip from: https://tex.stackexchange.com/questions/12010/how-can-i-invert-a-clip-selection-within-tikz \tikzset{invclip/.style={clip,insert path={{[reset cm] (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt) }}}}

% placeholder for the name of saveboxes defined in the spotlight macro \newcommand{\hilboxname}{somesecrethilboxname} % placeholder for the name of marks defined in the spotlight macro \newcommand{\hilboxmark}{somearbitraryhilboxmarkname} % spotlight padding in pt \newcommand{\hilboxpadding}{10} % counter to dinamically adjust the saveboxname \newcounter{hilboxcounter}

% macro to create a spotlight for the passed content \newcommand{\spotlight}[1]{% % create a savebox for the content \expandafter\newsavebox\csname \hilboxname\roman{hilboxcounter}\endcsname% \expandafter\savebox\csname \hilboxname\roman{hilboxcounter}\endcsname{#1}% % mark position and use savebox \tikzmark{\hilboxmark\roman{hilboxcounter}}\expandafter\usebox\csname \hilboxname\roman{hilboxcounter}\endcsname% % create the spotlight \begin{tikzpicture}[remember picture,overlay] % shortcuts for the calculations below (width, height, depth of the box, padding for the spotlight) \newcommand{\w}{\wd\csname \hilboxname\roman{hilboxcounter}\endcsname}; \newcommand{\h}{\ht\csname \hilboxname\roman{hilboxcounter}\endcsname}; \newcommand{\D}{\dp\csname \hilboxname\roman{hilboxcounter}\endcsname}; \newcommand{\p}{\hilboxpadding};

\begin{scope}
\begin{pgfinterruptboundingbox} % needed by the range definition of invclip
% draw a path around the text for the highlight
\path[invclip]
(pic cs:\hilboxmark\roman{hilboxcounter}) + (0,-\D-\p)
-- ++(\w+\p, -\D-\p)
-- ++(0, \h+\D+2*\p)
-- ++(-\w-2*\p, 0)
-- ++(0,-\h-\D-2*\p);
\end{pgfinterruptboundingbox} 

% fill the rest of the slide greyish
\fill[black, opacity=0.5] (current page.south west) rectangle (current page.north east);
\end{scope}
\end{tikzpicture}%
\stepcounter{hilboxcounter}%

}

\begin{document}

\begin{frame}{Example Slide}
    Some text here.

    \vspace{3em}

    \hspace{17em} Other text here.

    \vspace{3.2em}

    \hspace{8em} \spotlight{Highlights!}
\end{frame}

\end{document}

In case you prefer circles instead, you can use:

% define the radius of the circle to create
\pgfmathsetmacro{\r}{\p+max(\w,\h+\D))/2}
% draw a circle around the text
\draw[draw=none, invclip]
(pic cs:\hilboxmark\roman{hilboxcounter}) + (0.5*\w, 0.5*\h - 0.5*\D) circle (\r pt);

However, creating multiple highlights this way will darken the background even more. So I created a version with some more options.

cspotlight creates a circular spotlight. rspotlight creates a rectangular spotlight.

Appending a p allows you to increase the padding size.
Appending a d allows you to specify the slides the highlight should appear on.

These commands only work in an hframe. The idea simply that the hframe inserts the "darkening tikz picture". And the spotlight commands insert the spotlights. (Instead of creating multiple such tikzpictures as before.)

\documentclass[xcolor=dvipsnames]{beamer}
\usetheme{metropolis}
\metroset{block=fill}

\usepackage{tikz} \usetikzlibrary{tikzmark}

\usepackage{ifthen}

% invclip from: https://tex.stackexchange.com/questions/12010/how-can-i-invert-a-clip-selection-within-tikz \tikzset{invclip/.style={clip,insert path={{[reset cm] (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt) }}}}

% placeholder for the name of saveboxes defined in the spotlight macro \newcommand{\hilboxname}{somesecrethilboxname} % placeholder for the name of marks defined in the spotlight macro \newcommand{\hilboxmark}{somearbitraryhilboxmarkname} % standard spotlight padding in pt \newcommand{\hilboxpadding}{10} % counter to dinamically adjust the saveboxname \newcounter{hilboxcounter} % shortcut for hilboxcounter as number \newcommand{\hc}{\arabic{hilboxcounter}}

% generalized spotlight macro % #1 - mode % #2 - content % #3 - padding % #4 - higlight range \newcommand{\gspotlight}[4]{% % create a savebox for the content \expandafter\newsavebox\csname \hilboxname\hc\endcsname% \expandafter\savebox\csname \hilboxname\hc\endcsname{#2}% % mark position and use savebox \tikzmark{\hilboxmark\hc}\expandafter\usebox\csname \hilboxname\hc\endcsname% % save the spotlight info \only<#4>{% \ifthenelse{\equal{\highlightlist}{}}{% \edef\highlightlist{#1/\hc/#3}% }{% \edef\highlightlist{\highlightlist,#1/\hc/#3}% }% }% \stepcounter{hilboxcounter}% }

\newcommand{\rspotlight}[1]{\rspotlightp{#1}{\hilboxpadding}} \newcommand{\rspotlightp}[2]{\rspotlightpd{#1}{#2}{1-}} \newcommand{\rspotlightd}[2]{\rspotlightpd{#1}{\hilboxpadding}{#2}} \newcommand{\rspotlightpd}[3]{\gspotlight{creater}{#1}{#2}{#3}} % add rectangular spotlight % #1 - savebox number % #2 - padding \newcommand{\creater}[2]{ % shortcuts for the calculations below (width, height, depth of the box, padding for the spotlight) \def\w{\wd\csname \hilboxname#1\endcsname} \def\h{\ht\csname \hilboxname#1\endcsname} \def\D{\dp\csname \hilboxname#1\endcsname} \def\p{#2}

\path[invclip]
(pic cs:\hilboxmark#1) + (0,-\D-\p)
-- ++(\w+\p, -\D-\p)
-- ++(0, \h+\D+2*\p)
-- ++(-\w-2*\p, 0)
-- ++(0,-\h-\D-2*\p);

}

\newcommand{\cspotlight}[1]{\cspotlightp{#1}{\hilboxpadding}} \newcommand{\cspotlightp}[2]{\cspotlightpd{#1}{#2}{1-}} \newcommand{\cspotlightd}[2]{\cspotlightpd{#1}{\hilboxpadding}{#2}} \newcommand{\cspotlightpd}[3]{\gspotlight{createc}{#1}{#2}{#3}} % add circular spotlight % #1 - savebox number % #2 - padding \newcommand{\createc}[2]{ % shortcuts for the calculations below (width, height, depth of the box, padding for the spotlight) \def\w{\wd\csname \hilboxname#1\endcsname} \def\h{\ht\csname \hilboxname#1\endcsname} \def\D{\dp\csname \hilboxname#1\endcsname} \def\p{#2}

% define the radius of the circle to create
\pgfmathsetmacro{\r}{\p+max(\w,\h+\D))/2}
% draw a circle around the text
\draw[draw=none, invclip]
(pic cs:\hilboxmark#1) + (0.5*\w, 0.5*\h - 0.5*\D) circle (\r pt);

}

% A new environment that assumes the slide should have some highlighted words \newenvironment{hframe}[1]{% % there may be a nicer way to generally append something to a frame, this idea is from: % https://tex.stackexchange.com/questions/11708/run-macro-on-each-frame-in-beamer?rq=1 \begin{frame}[environment=hframe]\frametitle{#1}% \def\highlightlist{} }{% \ifthenelse{\equal{\highlightlist}{}}{}{% % create highlight overlay \begin{tikzpicture}[remember picture,overlay] \begin{scope} \begin{pgfinterruptboundingbox} \foreach \mode \number \padding in \highlightlist { \csname \mode\endcsname{\number}{\padding} } \end{pgfinterruptboundingbox}

        % fill the rest of the slide greyish
        \fill[black, opacity=0.5] (current page.south west) rectangle (current page.north east);
        \end{scope}
        \end{tikzpicture}%
    }%
\end{frame}%

}

\begin{document}

\begin{hframe}{Example Slide}
    Some text here.

    \vspace{3em}

    \hspace{17em} \rspotlightd{FIRST HIGHLIGHT}{2-}

    \vspace{3.2em}

    \hspace{8em} \rspotlightd{Highlights!}{3}
\end{hframe}

 \begin{hframe}{Example Slide}
    Some text here.

    \vspace{3em}

    \hspace{17em} \cspotlightd{FIRST HIGHLIGHT}{2-}

    \vspace{3.2em}

    \hspace{8em} \cspotlightpd{Highlights!}{20}{3} % increase the radius for this one
\end{hframe}

\end{document}

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

plauer
  • 438