为什么 \vspace 在节标题之后有时会以离散步骤跳跃/捕捉?

为什么 \vspace 在节标题之后有时会以离散步骤跳跃/捕捉?

嗯,这个问题我很久以前就想问过,而且总是让我非常恼火。不过,这次我甚至有点高兴——我可以问题根本;这要归功于动画 .gif 的强大功能:)

事情就是这样——有时我想在 Latex 中复制一些设计;通常你会阅读手册,更改长度,然后就会发生一些事情。但是,有时——尤其是在章节标题之后——我想说,在章节之后稍微抬起或推下起始段落;但是,在跳过后不重新定义主章节。

因此,我通常\vspace{\length}在节标题后插入一个,然后开始调整\length;文本开始移动,然后,如果我将其移动 1 pt,它几乎会跳到那个方向;我将其减少到 0.5 pt - 文本就好像根本没有移动一样?!(然后我开始尝试\vspace*,或者\ \\[\length],或者任何可行的方法)我一直想问这个问题——但我永远想不出比“为什么 Latex 会跳过垂直空间“,而且可以说没有人会明白发生了什么:)。好吧,最后,这就是我所说的“跳跃”或“以离散步骤”进行的“捕捉”的意思(测试动画,900KB):

测试动画

该图像的 MWE 如下(使用 编译pdflatex) - 但是,它是一个bash脚本,可生成 100 个 PDF,然后从中提取图像,最后将图像合成为动画 gif。基本上,对于每个“帧”(PDF),脚本都会更改一个参数,该参数最终会成为长度,\mylen,该参数仅在一个地方使用:\ \\[\mylen].\mylen在每个帧中以恒定的步长(小于 pt)增加;并写出为段落中的第一个单词。

请注意,段落不是平滑过渡,而是“卡入”到位,不会在某些值内移动 - 然后当它再次开始移动时,它会比平时“跳跃”得更多。这实际上是在某个步长为(请注意,在加载 gif 时,浏览器可能会出现一些问题;但是,一旦加载完成,当段落不动时,跳跃应该是显而易见的 - 并且数字指示仍然会发生变化……尽管如此,gif 中的某些帧可能仍会被丢弃

好吧,每当我遇到这个问题时,我都会因为难以用语言解释而感到沮丧。然后我想,好吧 - 让我编造一个 MWE,对其他人来说会更容易。然后我写了一些最小的东西,扔进\lipsum[1]去 - 我无法再演示问题了!!该死的,这总是让我很困惑!这就是为什么第一个 .gif(和 MWE)被设置为\lipsum[1-10]- 来演示问题;然而,如果使用,就会发生这种情况\lipsum[1-2]测试动画02.gif,899KB):

测试动画02.gif

也就是说 - 一切都进展顺利,正如预期的那样(还建有pdflatex)我偶然发现,除非你在段落中使用足够多的文本,否则你无法展示这种“跳跃性”,这样它就会流到下一页!

 

最后,为了好玩,我想生成这样一个动画 gif,但是用lualatexlua-visual-debug- 这当然解释了更多的事情(测试动画,1599KB):

测试动画

也就是说,这里值得注意的是,当段落“锁定”到垂直位置时 - 其中一条蓝线开始“向上”,然后“跳下来”; 然而,这是什么意思,我不知道:)

因此,如果有人可以解释这里发生了什么 - 并且是否有可能“平滑”地垂直定位溢出的段落,请回复...

非常感谢您的任何回答,
干杯!

以下是 MWE 脚本代码(文本测试工具):

#!/bin/bash

# to force exit loop:
trap 'echo Control-C trap caught; cleanup; exit 1' 2 #traps Ctrl-C (signal 2)

MYFN="atest"
MYFNIMG="${MYFN}_img"
MYFNTEX=${MYFN}.tex
MYFNIN="${MYFN}-input"
MYFNINTEX=${MYFNIN}.tex

function cleanup() {
  echo rm ${MYFNTEX} ${MYFNINTEX} -rf ${MYFN} -rf ${MYFNIMG}
  rm ${MYFNTEX} ${MYFNINTEX}
  rm -rf ${MYFN}
  rm -rf ${MYFNIMG}
}



mkdir ${MYFN}
mkdir ${MYFNIMG}

cat > ${MYFNTEX} <<EOF
\documentclass[10pt,a4paper]{article}
\providecommand{\myparam}{0.0pt}% fallback definition
\tracingonline=0 % suppress stdout (still dumps start)

% tex.se: 47576
\usepackage{ifxetex,ifluatex}
\newif\ifxetexorluatex
\ifxetex
  \xetexorluatextrue
\else
  \ifluatex
    \xetexorluatextrue
  \else
    \xetexorluatexfalse
  \fi
\fi

\ifluatex
  \usepackage{lua-visual-debug} % tlmgr install lua-visual-debug
\fi
\ifxetexorluatex
  \usepackage{fontspec}
  \defaultfontfeatures{Ligatures=TeX}
  \setmainfont[Scale=1.0]{Junicode}
  \newfontfamily\myfontfam[Scale=1.0]{Junicode}
\fi

\usepackage[a4paper]{geometry}
\geometry{twoside,inner=2.5cm,outer=3.5cm,top=2.5cm,bottom=2.5cm}

\makeatletter
\renewcommand{\section}{\@startsection
{section}%                   % the name
{1}%                         % the level
{\z@}%                       % the indent / 0mm
{-\baselineskip}%            % the before skip / -3.5ex \@plus -1ex \@minus -.2ex
{2pt}%          % the after skip / 2.3ex \@plus .2ex
{\centering\fontsize{11}{12}\selectfont\bfseries}} % the style
\makeatother

\usepackage{lipsum}


\newlength{\mylen}
\setlength{\mylen}{0pt}
\setlength{\mylen}{\myparam}

\begin{document}

\ifxetexorluatex
  \myfontfam
\fi
  \fontsize{10}{12.3}\selectfont

\title{Testing Title}
\date{October 31, 1000}
\author{John Doe\\\\ Somewhereland}

\maketitle

\clearpage

\input{${MYFNINTEX}}
\clearpage

\end{document}
EOF

cat > ${MYFNINTEX} <<EOF

\section*{Introductory words of introduction}

\vspace{\baselineskip}
\vspace{2pt}
\begin{center}
\textbf{Something else here, some other words}
\end{center}

%\vspace{\mylen}
\ \\\\[\mylen]

\makebox[2cm][r]{\the\mylen}, \lipsum[1-10] %[1-2]


\bigskip


\bigskip

EOF

MYPARAM="2.0pt"
JOBNAME="atest1"

#~ CROPPARAMS=320x240+100+400
CROPPARAMS=400x400+150+100

CMDNAME="pdflatex"
#~ CMDNAME="xelatex"
#~ CMDNAME="lualatex"

for ix in $(seq 0 1 100); do
  iy=$(wcalc -EE -q \($ix-50\)/50*30);
  INDEX=$(printf "%03d" $ix) ;
  JOBNAME="${MYFN}${INDEX}" ;
  MYPARAM="${iy}pt"
  echo "
        $CMDNAME - $JOBNAME - $MYPARAM" ;
  (${CMDNAME} -output-directory="${MYFN}" -jobname="${JOBNAME}" "\def\myparam{${MYPARAM}}\tracingonline=0\input{${MYFNTEX}}" 2>&1 1>/dev/null);
  convert -density 150 -crop ${CROPPARAMS} +repage ${MYFN}/${JOBNAME}.pdf[1] ${MYFNIMG}/${JOBNAME}.png ;
done

GRAY=""
#~ GRAY="-type grayscale"
echo convert -delay 5 -loop 0 ${MYFNIMG}/\*.png ${GRAY} ${MYFN}_animate.gif
convert -delay 5 -loop 0 ${MYFNIMG}/*.png ${GRAY} ${MYFN}_animate.gif


# view results
#~ evince ${MYFN}/${JOBNAME}.pdf
#~ display ${MYFNIMG}/${JOBNAME}.png
eog atest_animate.gif 2>/dev/null

cleanup # remove tmp files

答案1

因此,如果有人可以解释这里发生了什么 - 并且是否有可能“平滑”地垂直定位溢出的段落,请回复...

正如斯蒂芬所说,这是一个值得研究的非常好的问题,但我认为通过周围的动画和编码你已经相当有效地隐藏了这个问题。

罪魁祸首就是center您修改的空间前面的环境。问题在于这个环境被柔性胶水包围着(即带有拉伸和收缩组件)。您案例中的确切值是

10pt plus 3pt minus 5pt

所以在你有空间的地方你真的有

\mylength + 10pt plus 3pt minus 5pt

正如其他答案中提到的那样,TeX 会尝试找到一个错误最少的分页符。因此,如果我们假设 TeX 找到的分页符自然适合(即不需要收缩或拉伸),那么您就会得到\mylength + 10pt这个点。现在,如果您添加 1pt,\mylength那么最后一行将不再适合该页面,除非您的额外点可以通过页面上的收缩来吸收。

现在,如果唯一可用的收缩就在这个位置(在您的示例中就是如此),那么您的额外点将被吞噬,空间保持不变。添加另一个 pt 和另一个 pt 也是同样的情况。(如果页面上有多个位置有收缩,那么收缩会均匀分布在这些位置,因此在这种情况下,您可能会看到小幅增加,但小于您的步长值。)

但是一旦您添加了 4pt,它就无法通过示例中可用的收缩来补偿。因此,最后一行现在实际上不再适合页面,因此 TeX 需要使用“拉伸”来填充缺失的行(减去您的 4pt),即 8pt 左右,具体取决于设置\baselineskip

因此不再收缩,而是拉伸,您的空间会跳跃。添加更多点将增加您的空间,同时拉伸的需要会减少,直到您达到页面再次“自然”而不需要拉伸的点,然后一切重复。

现在,该\raggedbottom设置仅影响最终页面的排版方式(拆分后)。基本上,截断的页面会放入底部\textheight,如果是,\raggedbottom则会\vfill添加到底部(或多或少)。现在在“收缩”情况下,这实际上不会产生任何影响,因为页面已经满满的。而在拉伸情况下,这意味着最终的拉伸仅应用于底部,而不应用于页面中间的可拉伸部分。

总结一下:为了避免这种困惑,你需要确保你试图调整的空间没有收缩或拉伸组件,无论是作为调整的一部分还是作为视觉上相邻空间的一部分。只有这样,你才能确保空间实际上按照你的预期运行

答案2

LaTeX 默认将页面内容垂直对齐,从上到下分布在整个页面上,除非手动分页符之前(例如新章节或使用\newpage\clearpage或在文档末尾)。

为了实现这一点,页面上的每个垂直空间都配备了一些拉伸。即使基线跳过也具有拉伸,因此段落行不需要保持相同的距离。就您而言,LaTeX 似乎使用\\您用来产生空间的换行符中的(负)拉伸。请尝试使用\vspace*{10.0pt}

通常,从格式定义长度中删除拉伸不是一个好主意,因为如果页面上根本没有垂直拉伸(即没有段落间、行间或节间距拉伸),页面将变得“短”,LaTeX 将无法填满整个页面,并将Warning: Underfull \vbox while \output is active出现在日志文件中。页面的高度将不相等,这会让您的文档看起来很丑陋。

答案3

GIF 图像很棒,bash 脚本功夫更棒,但是查看页面顶部和底部很有启发。首先,这是一张略有不同的页面图像,没有任何\vspace添加。

在此处输入图片描述

请注意,文本从第 4 行开始,以单词“donee”结尾。

接下来的两幅图像设置\vspace*16pt18pt

\vspace*{16pt}

在此处输入图片描述

设置为“\vspace{18pt}”

在此处输入图片描述

你所经历的跳跃(特别是如果你使用vspace而不是带星号的版本),是 TeX 试图始终生成一个包含最少坏處。

这是一个老问题,在约瑟夫·莫克森 (Joseph Moxon) 出版的第一部关于印刷术的著作 (1683 年) 中,机械练习:或者,手工理论应用于印刷艺术,提到添加空格来平衡文本,以便最后一行始终位于同一位置并使页面均匀。

开始了解相关问题的最佳地点是 Michael Plass 的博士论文,自动排版系统的最佳分页技术

图像的 MWE 代码如下,如果您能将其与您的 GIF 结合起来就更好了。注意并观察 TeX 总是试图以漂亮的页面显示结束,这是很有启发的。

\documentclass[10pt,twoside]{article}
\usepackage{fancyhdr,lipsum}
\makeatletter
 \newsavebox{\@linebox}
 \savebox{\@linebox}[3em][t]{\parbox[t]{3em}{%
   \@tempcnta\@ne\relax
   \loop{\underline{\the\@tempcnta}}\\
     \advance\@tempcnta by \@ne\ifnum\@tempcnta<48\repeat}}
 \pagestyle{fancy}
 \fancyhead{}
 \fancyfoot{}
 \fancyhead[CO]{\scriptsize How to Count Lines}
 \fancyhead[RO,LE]{\footnotesize\thepage}
%% insert this block within a conditional
 \fancyhead[LE]{\footnotesize\thepage\begin{picture}(0,0)%
      \put(-26,-25){\usebox{\@linebox}}%
      \end{picture}}
 \fancyhead[LO]{%
    \begin{picture}(0,0)%
      \put(-18,-25){\usebox{\@linebox}}%
     \end{picture}}
\fancyfoot[C]{\scriptsize Draft copy}
%% end conditional
\makeatother
\begin{document}
%\rule{10pt}{18pt}Latey
\section*{Introduction}
\vspace*{3pt}
\lipsum[1]

$$f_{nk}=\sum\,{\frac{n!}{
1!^{k_1}\,k_1!\,2!^{k_2}\,k_2!\,3!^{k_3}\,k_3!\,\ldots}}\; 
f_1^{k_1}f_2^{k_2}f_3^{k_3}\ldots\;,$$
summed over all $k_1,k_2,k_3,\ldots\geq 0$ 

\lipsum[3]

$$f_{nk}=\sum\,{\frac{n!}{
1!^{k_1}\,k_1!\,2!^{k_2}\,k_2!\,3!^{k_3}\,k_3!\,\ldots}}\; 
f_1^{k_1}f_2^{k_2}f_3^{k_3}\ldots\;,$$
summed over all $k_1,k_2,k_3,\ldots\geq 0$ 

\lipsum[5-12]
\end{document}

答案4

编辑:好的,按照@tohecz' 线程,这不仅仅是关于使用星号\vspace*;按照@YiannisLazarides线程,避免\begin{center}帮助 - 这也解释了@FrankMittelbach的帖子。

因此,在OP Latex代码中,显示的页面是:

\clearpage

\section*{Introductory words of introduction}

\vspace{\baselineskip}
\vspace{2pt}
\begin{center}
\textbf{Something else here, some other words}
\end{center}

\ \\\\[\mylen]

\makebox[2cm][r]{\the\mylen}, \lipsum[1-10] 

\bigskip
\bigskip
\clearpage

我将其替换为(文本测试集b-sh-woc.diff):

\clearpage

\section*{Introductory words of introduction}

\vspace{\baselineskip}
\vspace{2pt}
{ % begin group 
\centering\textbf{Something else here, some other words}
} % end group

\vspace{\mylen}

\makebox[2cm][r]{\the\mylen}, \lipsum[1-10] 

\bigskip
\bigskip
\clearpage

... 我可以确认:删除环境,并用带有 的组center替换它,现在将导致段落开头的“平滑”垂直空间过渡;如图所示{}\centering\vspace动画我觉得我最好不要再发内联动图了,这个页面可能四张就够了:))。

不幸的是,该\centering部分不能适应这种变化(标题没有居中);但至少最终确定并确认了垂直空间跳跃的“罪魁祸首”。

\centering编辑:好的,我可以确认,如果我将节包装在命令中,独立文本的居中已恢复,\makebox如下所示:

 
{ % 开始组
\makebox[\textwidth][c]{
\centering\textbf{这里还有其他东西,其他一些词语}
}
} % 结束组
但是,部分文本的位置比以前的位置稍微低了一点;并且文本段落的位置与以前的位置不同,这与相同的\vspace范围(此处为 -30pt 到 30 pt)不同。但是,\vspace部分标题和第一段之间的 - 确实会平滑地变化;此 hack 的动画位于测试_动画_l_tb_wocm.gif

为了更容易比较动画 .gif,我能找到的唯一方法是先使用 ImageMagick 的convert(方法 2 来自“动画修改:并排附加(时间同步)"):

convert atest_animate.gif -repage 1208x402 -coalesce null: \( atest_animate_l_tb_woc.gif -coalesce \) -geometry +604+0 -layers Composite out.gif

(注意上面的命令会疯狂地交换和占用 CPU,但可能比其他方法要少)然后查看:display out.gif在 ImageMagick 的display查看: 。我还没有找到其他类似的查看器工具,可以通过动画 gif 帧进行某种步骤控制(哎呀甚至不支持动画 GIF - 只显示第一帧
请注意,gif 可能会以每秒一帧的慢速开始播放display,目前还没有找到停止它的方法 - 但是,display的键盘快捷键 SPACE并且BACKSPACE仍然可以转到序列中的下一个和上一个图像 - 因此人们可以稍微关注单个 gif 帧的比较。


回应@Mico 和@StephanLehmke - 下面是一个 gif,其中包含左上角(段落开头;动画左侧)和左下角(页面末尾;动画右侧)的片段;在线脚本文本测试工具已做了相应改变。

该图像与 OP 中的条件相同 - 除了使用 进行编译外lualatex,但fontspec删除了内容(测试动画):

哈哈 - 好像 imgur 从昨天到今天都禁用了动画 gif(要么是我没有启用其中一个 JavaScript 域);下面是来自 sourceforge 的原始图像:

\raggedbottom我看不出与(有什么区别动画) - 但是,有一个有趣的区别flushbottom测试_动画_l_tb_flushbottom.gif):

这里的平滑间隔似乎更长 - 但跳跃也更大......

相关内容