为什么列表前会有这么虚假的垂直空间?

为什么列表前会有这么虚假的垂直空间?

尝试回答我在评论中提出的问题这个答案,我最终根据 Ulrike 的代码得到了下面的代码,但该代码使\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

这里没有什么魔法:您\tikz[overlay]在某些框架中插入 ,而在其他框架中不插入 。 A\tikz[overlay]可能没有大小,但它仍然是一个框,并且像 一样,\mbox{}它可以引入空格。这意味着重要的是要么\tikz[overlay]在这样的框不会造成伤害的地方使用 。或者在所有框架中使用类似的框,例如使用 David 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 在这里到底在做什么,但是添加了 invisible什么东西在垂直模式下,无论\color\label总是\tikzmark很棘手,并且很难控制副作用。在所有情况下,解决方案都是在执行任何棘手操作之前先安全进入水平模式。

如果你

\mbox{\balloon<3>{comment}{5}{6}%
\balloon<4>{comment}{1}{3}}%

然后列表就会出现在所有四张幻灯片的相同位置。空的 mbox 会形成一个虚假的段落,将内容向下移动一点,但由于它是一个固定点,并且在所有幻灯片上都相同,因此您可以在框后使用空白行和负 vspace(如果需要)。

相关内容