Зачем нужны такие лишние вертикальные пробелы перед объявлениями?

Зачем нужны такие лишние вертикальные пробелы перед объявлениями?

Пытаюсь ответить себе на вопрос, заданный в моем комментарииэтот ответ, я закончил с кодом ниже, основанным на коде Ульрике, но который делает \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 после поля, если это необходимо.

Связанный контент