
Пытаюсь ответить себе на вопрос, заданный в моем комментарииэтот ответ, я закончил с кодом ниже, основанным на коде Ульрике, но который делает \balloon
макрос оверлеем осведомленным. Но, когда используется перед листингами, этот макрос вводит ложный вертикальный пробел. Вы видите, откуда это может взяться?
Обновлять
Код был немного изменен и добавлена анимация, чтобы сделать ложное вертикальное пространство более заметным.
Обновление 2
На самом деле, чтобы избежать проблем из-за дубликатов при создании \balloon
наложений, необходимо, чтобы списки имели разные имена. Использование для этого номеров слайдов ( \the\beamer@slideinframe
) достаточно в пределах данного кадра, но недостаточно для всего документа. Добавление номеров кадров ( \insertframenumber
) решает проблему.
\documentclass{beamer}
%
\setbeamertemplate{footline}[page number]
%
\usepackage{listings}
\usepackage[foreground]{pagegrid}
\usepackage{tikz}
\usetikzlibrary{tikzmark,fit,calc}
\usetikzmarklibrary{listings}
\lstset{basicstyle=\ttfamily}
\tikzset{%
balloon/.style={%
draw,%
fill=blue!20,%
opacity=0.4,%
inner sep=4pt,%
rounded corners=2pt%
},%
}
%
\makeatletter
\renewcommand\iftikzmark[3]{%
\@ifundefined{save@pt@#1-\the\beamer@slideinframe}{%
#3%
}{%
#2%
}%
}%
\newcommand{\@balloon}[4]{%
\pgfmathtruncatemacro\@firstline{%
#3-1%
}%
\iftikzmark{line-#2-\@firstline-start}{%
\iftikzmark{line-#2-#3-first}{%
\xdef\@blines{%
($ ({pic cs:line-#2-\@firstline-start} -| {pic
cs:line-#2-#3-first})!.5!({pic cs:line-#2-#3-first}) $)%
}%
}{%
\iftikzmark{line-#2-#3-start}{%
\xdef\@blines{%
({pic cs:line-#2-\@firstline-start} -| {pic cs:line-#2-#3-start})%
}%
}{%
\xdef\@blines{(pic cs:line-#2-\@firstline-start)}%
}%
}%
}{%
\xdef\@blines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first}{%
\xdef\@blines{%
\@blines (pic cs:line-#2-\k-first)%
}%
}{}%
\iftikzmark{line-#2-\k-end}{%
\xdef\@blines{%
\@blines (pic cs:line-#2-\k-end)%
}%
}{}%
}%
\ifx\@blines\empty%
\else%
\edef\temp{\noexpand\tikz[remember picture,overlay]%
\noexpand\node[fit={\@blines},balloon] (#1) {};}%
\temp%
\fi%
}
%
\newcommand<>{\balloon}[4][code\insertframenumber\the\beamer@slideinframe]{%
\only#5{\@balloon{#2}{#1}{#3}{#4}}%
}
%
\lstnewenvironment{hllisting}[1][]{%
\lstset{name=code\insertframenumber\the\beamer@slideinframe,#1}%
}{%
\lstset{name=}%
}
\makeatother
%
\begin{document}
\begin{frame}[fragile]
\balloon<3>{comment}{5}{6}%
\balloon<4>{comment}{1}{3}%
\begin{hllisting}
1st line of code
2nd line of code
3rd line of code
4th line of code
5th line of code
6th line of code
\end{hllisting}
\end{frame}
\end{document}
решение1
Здесь нет никакой магии: вы вставляете a \tikz[overlay]
в некоторые рамки и не в другие. A \tikz[overlay]
может не иметь размера, но это, тем не менее, коробка и, как и a, \mbox{}
может вводить пробелы. Это означает, что важно либо использовать \tikz[overlay]
в тех местах, где такая коробка не навредит. Либо использовать подобную коробку во всех рамках, например, используя, как предложил Дэвид, an \mbox
или eg \alt
вместо \only
в определении \balloon
:
\documentclass{beamer}
%
\setbeamertemplate{footline}[page number]
%
\usepackage{listings}
\usepackage[foreground]{pagegrid}
\usepackage{tikz}
\usetikzlibrary{tikzmark,fit,calc}
\usetikzmarklibrary{listings}
\lstset{basicstyle=\ttfamily}
\tikzset{%
balloon/.style={%
draw,%
fill=blue!20,%
opacity=0.4,%
inner sep=4pt,%
rounded corners=2pt%
},%
}
%
\makeatletter
\renewcommand\iftikzmark[3]{%
\@ifundefined{save@pt@#1-\the\beamer@slideinframe}{%
#3%
}{%
#2%
}%
}%
\newcommand{\@balloon}[4]{%
\pgfmathtruncatemacro\@firstline{%
#3-1%
}%
\iftikzmark{line-#2-\@firstline-start}{%
\iftikzmark{line-#2-#3-first}{%
\xdef\@blines{%
($ ({pic cs:line-#2-\@firstline-start} -| {pic
cs:line-#2-#3-first})!.5!({pic cs:line-#2-#3-first}) $)%
}%
}{%
\iftikzmark{line-#2-#3-start}{%
\xdef\@blines{%
({pic cs:line-#2-\@firstline-start} -| {pic cs:line-#2-#3-start})%
}%
}{%
\xdef\@blines{(pic cs:line-#2-\@firstline-start)}%
}%
}%
}{%
\xdef\@blines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first}{%
\xdef\@blines{%
\@blines (pic cs:line-#2-\k-first)%
}%
}{}%
\iftikzmark{line-#2-\k-end}{%
\xdef\@blines{%
\@blines (pic cs:line-#2-\k-end)%
}%
}{}%
}%
\ifx\@blines\empty%
\else%
\edef\temp{\noexpand\tikz[remember picture,overlay]%
\noexpand\node[fit={\@blines},balloon] (#1) {};}%
\temp%
\fi%
}
%
\newcommand<>{\balloon}[4][code\the\beamer@slideinframe]{%
\alt#5{\@balloon{#2}{#1}{#3}{#4}}{\tikz[overlay,remember picture]\path (0,0);}%
}
%
\lstnewenvironment{hllisting}[1][]{%
\lstset{name=code\the\beamer@slideinframe,#1}%
}{%
\lstset{name=}%
}
\makeatother
%
\begin{document}
\begin{frame}
\tikz[overlay]\node{a};
blblb
\end{frame}
\begin{frame}
blblb
\end{frame}
\begin{frame}[fragile]
\balloon<3>{comment}{5}{6}%
\balloon<4>{comment}{1}{3}%
\begin{hllisting}
1st line of code
2nd line of code
3rd line of code
4th line of code
5th line of code
6th line of code
\end{hllisting}
\end{frame}
\end{document}
решение2
Как ни странно, я не до конца проследил, что именно здесь делают beamer и tikzmark, но добавление невидимыхчто этов вертикальном режиме, будь то \color
или \label
или \tikzmark
всегда сложно и имеет трудно контролируемые побочные эффекты. Решение во всех случаях — безопасно перейти в горизонтальный режим, прежде чем делать что-то сложное.
Если ты это сделаешь
\mbox{\balloon<3>{comment}{5}{6}%
\balloon<4>{comment}{1}{3}}%
тогда список появляется в той же позиции на всех четырех слайдах. Пустой mbox создает ложный абзац, который немного сдвигает все вниз, но поскольку это фиксированная точка и она одинакова на всех слайдах, вы можете использовать пустую строку и отрицательный vspace после поля, если это необходимо.