这个问题引出了包中的一个新功能:
multicol
我的包有问题multicol
,我创建了一个示例演示来展示它。
当我minipage
在其中放置 3 个特定高度的multicol
框时,它会将其中 2 个框放在第一列,但第二个框太大而无法容纳该列(溢出页面),应该移至第二列。LateX 甚至会输出消息Overfull \vbox (145.52644pt too high) has occurred while \output is active
。
但是如果我将第二个框的高度改为40em
,它会很好用,而且如果我使用不平衡的列(multicols*
),那么它也能很好地工作,但我需要平衡列,并且我需要它自动处理列。
\documentclass[12pt]{article}
\usepackage[paperwidth=8.5in, paperheight=11.0in, right=.25in,left=.25in,top=.75in,bottom=0.75in]{geometry}
\usepackage{multicol}
\newcommand{\drawbox}[1]
{
% Draws a simple box given the height
\noindent\fbox{%
\begin{minipage}{0.9\linewidth}%
\hfill \vspace{#1}%
\end{minipage}
} \\
}
\begin{document}
\begin{multicols}{2}
\drawbox{40em}
% This box is too big to fit in the fist column, but would work great in the second colum
\drawbox{30em}
\drawbox{40em}
\end{multicols}
\end{document}
答案1
这是非常不合适的输入 ;-) 和多列的缺陷的混合。Multicol 最初是为文本平衡而设计的,算法基于此做出了一些假设。其中一个假设是,要从中截取列的样张材料具有适当数量的断点,可以实现这一点,特别是可以实现平衡。现在您的示例有两个属性:
- 断点很少
- 尽管如此,材料还是可以放在一页纸上(如果可以拆分的话)。当
\drawbox
用两个方框替换第二个方框时,可以看到后者15em
。然后突然一切都平衡了,仍然适合放在页面上。
算法
现在平衡算法的工作原理大致如下:
- 它测量整个厨房的平衡度,并根据该值推断出切割柱子的起始值。该起始点可能会受到影响,但在这里这无济于事。
- 然后它切断柱子,最后一列接收所有剩余的材料。然后它检查最后一列的高度是否高于第一列的高度,如果是,则拒绝该解决方案。
- 如果任何列的不良程度非常高(可定制),它也会拒绝当前试验。
- 如果有未遵守的列分隔符,它也会拒绝试验。
- 如果试验成功,则将使用找到的值,而不是将其增加一个点并重复算法。
如果最终值大于可用空间,则 multicol 会尝试通过将所有列压缩到可用空间中进行恢复。对于普通文本列,此方法可能会成功,因为页面上通常存在一些可收缩性,并且如果样张中有足够的断点,则超出量也不太可能很高。
应用于本示例
在这个例子中,这种方法当然会失败,因为算法会循环直到列高足够容纳第一列中的两个框(较小的切割值总是会使第二列太大)。当这种情况发生时,列大小与可用空间相差甚远,以至于任何压缩(即使有任何可以压缩的东西)都无济于事。
解决此问题的手动解决方案是在源中输入明确的分页符,即
\drawbox{30em} \pagebreak
这样 multicol 就会停止收集数据,然后生成一个正常页面。但这肯定是劳动密集型的,而且每当文档发生变化时就需要进行更改。
另一种方法是使用multicols*
,但是这又有一个很大的缺点,那就是你根本无法平衡,因此第三页之后的任何文本\drawbox
都会出现在下一页上,而不是(因为它可以)继续在同一页上。
多糖缺乏症(?)
现在有人可能会说,如果 multicol 进行平衡并找到类似上述示例的解决方案,它也应该拒绝该解决方案。但它接下来应该做什么呢?
一种可能性是得出结论,平衡毕竟不是正确的方法,而是先裁切另一张“正常”页面,然后在剩余的材料上进行平衡。对于这个特定示例,这种方法同样非常有效。但是,如果您查看以下示例,结果至少会值得怀疑:
\documentclass{article}
\usepackage[balancingshow]{multicol}
\setlength\textheight{5\baselineskip}
\begin{document}
\begin{multicols}{2}
1\\2\\3\\4\\5\\6
1\\2\\3\\4\\5\\6
\end{multicols}
\end{document}
使用当前算法,这将导致一页(略微过满)每列有六行,而使用拒绝这种平衡的算法,将导致第二页有两页每列只有一行。
所以现在我不确定这里最好的方法是什么。也许这需要另一个参数,例如\balancingoverflow
保存平衡中的列允许“过满”的数量。
无论如何,我昨晚确实写了一个原型,可以做到这一点,如果有人想玩一下,请给我的“latex-project.org”地址发送电子邮件。
更新
我决定使用\maxbalancingoverflow
默认为 12pt 的参数来实现这个新功能。新版本还修正了从右到左排版的算法。可以从 LaTeX2e SVN 源中获得:多列文件对于那些想立即试用它的人来说。随着 LaTeX2e 的下一个版本发布,它将出现在 CTAN 上。
截至 2014 年 5 月,CTAN 发布了包含此功能的新 LaTeX 版本。
答案2
显而易见的解决方案不是尝试平衡列,即使用multicols*
而不是multicols
。这可能不是您想要的。
多列包尽力解决 LaTeX 中多列排版的大多数问题,但它仍然无济于事,因为 LaTeX 不是为这些问题而设计的。如果您想要更好的解决方案,您应该切换到 ConTeXt。
当然,你可以将此作为 LaTeX 项目的错误进行归档,但我怀疑 Frank 不会高兴。
答案3
如果您想在双列工作流程中拥有多个小页面,我可以为不平衡的列提出一个案例吗?
虽然multicols*
最后一页的列不平衡,但其他页面上仍然可能出现困难。
使用\raggedcolumns
withmulticols
会导致每页的列不平衡。
在我看来,第二种选择可以让单个项目看起来不错,无需手动或详细干预(例如,通过调整 TeX 设置或移动项目来尝试改善适配,以防止单个文本块过度垂直拉伸。)我使用这样的结构来制作每周 2 列文档,其中包含多个简短或中等大小的项目,可能包括标题、副标题、多个段落和插图。我不希望任何单个文章分散在一列或一页上。我确实尝试过平衡列,但发现这很耗时,而且看起来有些混乱。
如果材料块无序且至少有些较短,那么您可以移动内容以允许排版引擎进行调整以生成平衡的列,但结果即使如此也可能令人失望。允许整个列不规则可以对项目进行排序(例如日记项目的日期顺序或重要性顺序或确定哪些文章获得“最佳”位置),并且只有严重不平衡才需要手动干预(例如三篇连续的文章每篇都超过半列,而至少两列连续的列大部分为空白)。它还可以加快工作流程,使我能够专注于内容和 TeX 以生成有吸引力的排版输出。