图片

只考虑 pdflatexxelatex 这两种编译引擎,考虑的图片格式包括:矢量图(pdf, eps),位图(png, jpg)。两种编译引擎都直接支持这些图片格式。

includegraphics

LaTeX 本身不支持插图功能,需要 graphicx 宏包提供支持(或者更基础的 graphics 宏包,graphicx 宏包相当于其扩展)

1
\usepackage{graphicx}

导入这个宏包之后,就可以使用 \includegraphics 命令来插入图片

1
\includegraphics[<options>]{<filename>}

例如

1
2
\includegraphics{example.png}
\includegraphics{figure/example.png}

这里的图片文件名可以用相对路径或绝对路径表示,但是文件名里不要有空格或其它特殊符号,否则宏包在解析文件名的过程中会出错。
图片文件的后缀名一般可以省略不写,编译时会自动补充。

在省略图片文件后缀时,如果存在多个仅后缀不同的图片文件,显然有具体的查找顺序,测试发现似乎会优先选择 pdf 格式。

对于 eps 格式的图片,因为涉及到自动转换为 pdf 格式,所有省略后缀与否可能对pdflatex的编译产生明显影响。pdflatex在编译时会尝试执行类型转换,自动在demo.eps图片所在目录生成demo-eps-converted-to.pdf

完整示例如下

1
2
3
4
5
6
7
8
9
\documentclass{article}
\usepackage{graphicx}

\begin{document}

\noindent
\includegraphics[width=0.5\textwidth]{figure/demo}

\end{document}

graphicx 宏包提供了 \graphicspath 命令,用于声明图片文件的存放目录,在搜索图片时会自动去这些目录中寻找,例如

1
\graphicspath{{./figure/}{./figures/}{./image/}{./images/}{./graphic/}{./graphics/}}

这些目录是常见的存放图片的目录,即使目录不存在也不会报错。

\includegraphics 命令支持如下几个常见选项:

  • width=<width>:将图片缩放到宽度为 <width>
  • height=<height>:将图片缩放到高度为 <height>
  • scale=<scale>:将图片相对于原尺寸缩放 <scale>
  • angle=<angle>:将图片逆时针旋转 <angle>

例如

1
2
% 将图片缩放到宽度为文本宽度的一半,并逆时针旋转 45 度
\includegraphics[width=0.5\textwidth, angle=45]{example.png}

指定宽度是最常见的需求,例如width=0.8\textwidth代表将图片宽度缩放到 80% 的文本宽度。

graphicx 宏包支持草稿选项:当 graphicx 宏包或文档类指定 draft 选项时,图片将不会被实际插入,取而代之的是一个包含文件名的与原图片等大的方框,这有助于加速编译。

浮动体 figure

\includegraphics 命令只能就地插入图片,但是正文中可能包含许多图片和表格等内容,这些内容的尺寸往往太大,导致与文字的排版困难,效果非常混乱,LaTeX 为此引入了浮动体的机制,对浮动体的排版允许脱离原始的上下文,自动填入合适的位置。

LaTeX 预定义了两类浮动体环境:figuretable。习惯上在 figure 中放置图片,在 table 中放置表格,但并没有严格限制,实际上可以在其中放置任意内容。两种浮动体环境的用法类似,下面讨论 figure 环境。

figure环境被用来包裹最基本的命令,得到浮动的图片,例如

1
2
3
4
\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\end{figure}

习惯上对于浮动图片都会使用\centering命令使图片水平居中放置。

浮动体的使用主要是如下的几个浮动规则参数:

  1. h (here):允许放置在当前上下文位置
  2. t (top):允许放置在当前页或后续页面的顶部
  3. b (bottom):允许放置在当前页或后续页面的底部
  4. p (page):允许放置在一个独立页面中

我们可以选择开启其中的部分规则,例如[hbp]就指定允许基于这三种规则来放置浮动体,默认设置为tbp

可以在选项中加上!来忽略 LaTeX 对浮动体排版的默认限制,默认限制包括:

  • 浮动体个数:除单独成页外,默认每页不超过 3 个浮动体,其中顶部不超过 2 个,底部不超过 1 个。
  • 浮动体空间占页面的百分比:默认顶部不超过 70%,底部不超过 30% 。

需要注意的是:在实际排版时,对浮动体放置规则的选择顺序是固定的(h-t-b-p),与写法无关,例如[!htp][ph!t]是完全一样的。

在双栏排版环境下,LaTeX 还提供了 table*figure* 环境用来排版跨栏的浮动体,它们的用法与 tablefigure 类似,不同之处为横跨双栏的浮动体只允许使用tp 两个规则。

float 宏包为浮动体环境提供了 H 位置参数,不要与 htbp! 混用。使用 H 位置参数时,会取消浮动机制,将浮动体视为一般的盒子插入当前位置。

浮动体提供了 \caption 命令添加标题,此时会自动给浮动体编号,\caption 命令之后还可以紧跟 \label 命令标记交叉引用。
例如

1
2
3
4
5
\begin{figure}[htbp]
\centering
\includegraphics{demo.png}
\caption{Title}\label{fig:1}
\end{figure}

一个值得注意的细节:\caption 命令的位置也比较重要:

  • 如果 \caption 命令放在 \includegraphics 命令之前,则标题在图片上方;
  • 如果 \caption 命令放在 \includegraphics 命令之后,则标题在图片下方。

习惯上,图片的标题建议放置在图片下方,而表格的标题建议放置在表格上方。

与编号的\caption命令类似,\caption* 命令会生成不带编号的标题,但是这个命令是caption宏包提供的。

下面是实践中常用的插入图片的代码片段:

  • 不含标题的图片
1
2
3
4
\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\end{figure}
  • 含有标题和标签的图片
1
2
3
4
5
\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\caption{Results}\label{fig:result1}
\end{figure}

多个子图

我们时常有在一个浮动体里面放置多张图的用法(通常是并列子图),有非常多的方法可以实现这样的效果,有的不依赖宏包,有的依赖宏包。

第一种方案如下,直接在一个浮动体中使用两次\includegraphics命令,在两个图片之间需要指定间距

1
2
3
4
5
6
7
\begin{figure}
\centering
\includegraphics[width=...]{a.jpg}
\hspace{1in} % or \qquad
\includegraphics[width=...]{b.jpg}
\caption{Demo}
\end{figure}

但是这种方案只能使用一个\caption命令,只有一个图片标题(和标签),对两个宽度和间距需要具体调整。

第二种方案如下,创建两个minipage环境,此时两个图片可以有独立的标题和标签

1
2
3
4
5
6
7
8
9
10
11
12
\begin{figure}
\begin{minipage}{...}
\centering
\includegraphics[width=...]{a.jpg}
\caption{Demo 1}\label{fig:a}
\end{minipage}
\begin{minipage}{...}
\centering
\includegraphics[width=...]{b.jpg}
\caption{Demo 2}\label{fig:b}
\end{minipage}
\end{figure}

这种方案也比较麻烦,需要控制很多的宽度。

上面两种方案看起来都太原始了,当我们需要更进一步,给每个图片定义小标题时,就要通过 subcaption 宏包实现。

1
\usepackage{subcaption}

实际上有很多宏包可以实现多个子图的功能,例如subfigure(版本过旧,被弃用),subfigsubcaption。这些宏包相互之间是冲突的,有的版本过旧已经被舍弃,目前只建议使用subcaption

使用 subcaption 宏包可以给每个子图定义单独的标题和标签,子图的编号与父图的编号具有上下级关系,例如Fig. 3.1(a)

使用 subcaption 宏包的代码片段如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\begin{figure}[htbp]
\centering
\begin{subfigure}[b]{0.47\textwidth}
\centering
\includegraphics[width=\textwidth]{a.png}
\caption{Demo a}\label{fig:subfig-a}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.47\textwidth}
\centering
\includegraphics[width=\textwidth]{b.png}
\caption{Demo b}\label{fig:subfig-b}
\end{subfigure}
\caption{Demo}\label{fig:example}
\end{figure}

其中的\hfill命令会插入弹性的水平间距,比固定的\qquad更合适。

虽然subfigure宏包已经被弃用了,但是鉴于我之前使用过,还是记录一下对应的代码片段。

1
2
3
4
5
6
7
8
9
10
11
12
% \usepackage{subfigure}

\begin{figure}[htbp]
\centering
\subfigure[Demo a]{
\includegraphics[width=7.25cm]{a.png}
}
\subfigure[Demo b]{
\includegraphics[width=7.25cm]{b.png}
}
\caption{Demo}\label{fig:1}
\end{figure}

给透明图片添加底色

有时图片可能是透明的,直接放置到现有背景上可能难以辨识,可以给图片加一个底色,例如

1
2
3
4
5
6
\begin{figure}[htbp]
\centering
{\colorbox{white}
\includegraphics[width=0.8\textwidth]{demo.png}
}
\end{figure}

表格

在 LaTeX 中,表格功能由 tabular 环境提供,与图片类似的浮动机制由 table 环境提供。常见的表格类型包括普通文本表格、带线表格、跨列/跨行表格、以及更复杂的长表格和三线表格。

tabular

LaTeX 内置的 tabular 环境用于创建最基本的表格,其语法为

1
2
3
4
\begin{tabular}{<alignment>}
<cell_11> & <cell_12> & ... \\
<cell_21> & <cell_22> & ... \\
\end{tabular}

其中 <alignment> 用于指定每一列的对齐方式:

  • l:左对齐(left)
  • c:居中对齐(center)
  • r:右对齐(right)

在表格内部:

  • 每一行的单元格之间使用 & 分隔,实际使用的单元格数目可以等于或少于 <alignment> 声明的列数,此时后面的单元格留空;
  • 表格内部的正常换行不会对应表格换行,必须每一行的末尾使用 \\ 手动换行(包括最后一行)。

一个简单示例如下:

1
2
3
4
5
\begin{tabular}{lcr}
A & B & C \\
AA & BB & CC \\
AAA & BBB & CCC \\
\end{tabular}

输出为一个三行三列的表格,依次为左中右对齐,不含任何边框线。

<alignment> 还支持更丰富的效果,包括:

  • p{<width>}:固定单元格的宽度,如果超出会自动折行
  • @{<string>}:在单元格之间插入固定的文本内容,如果留空 @{} 则会消除默认的单元格之间的间距,例如 @{}ccc@{} 可以消除表格两端的空白。

添加边框线

<alignment> 中使用 | 可以添加竖线,在表格内部使用 \hline 可以添加横线。例如:

1
2
3
4
5
6
7
8
\begin{tabular}{|l|c|r|}
\hline
A & B & C \\
\hline
AA & BB & CC \\
AAA & BBB & CCC \\
\hline
\end{tabular}

这样就会得到一个带边框和一些横线的表格。

除了跨越整个表格的横线命令 \hline,还有更灵活的横线命令 \cline,接受两个参数指定横线开始和结束的列(闭区间,允许两个值相同)

1
\cline{i-j}

例如

1
2
3
4
5
6
7
8
9
\begin{tabular}{|c|c|c|}
\hline
4 & 9 & 2 \\
\cline{2-3}
3 & 5 & 7 \\
\cline{1-1}
8 & 1 & 6 \\
\hline
\end{tabular}

浮动体 table

tabular 很少直接使用,通常嵌入浮动体环境 table 中,用法与图片对应的 figure 环境类似。

例如

1
2
3
4
5
6
7
8
9
10
11
12
\begin{table}[htbp]
\centering
\caption{Demo Table}\label{tab:demo}
\begin{tabular}{|l|c|r|}
\hline
A & B & C \\
\hline
AA & BB & CC \\
AAA & BBB & CCC \\
\hline
\end{tabular}
\end{table}

浮动规则 [htbp]、标题命令 \caption 与图片浮动体一致。

习惯上在浮动体中将图片的标题放置在下方,而表格的标题则放置在上方。

有时需要在表格下面添加一些简短的注释,可以在 table 环境内部使用脚注字体实现,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\begin{table}[htbp]
\centering
\caption{Demo Table}\label{tab:demo}
\begin{tabular}{|l|c|r|}
\hline
A & B & C \\
\hline
AA & BB & CC \\
AAA & BBB & CCC \\
\hline
\end{tabular}

\vspace{2ex}
{\footnotesize xxx,yyyy,zzz}
\end{table}

合并单元格

表格排版的一个常见需求是合并单元格,包括横向合并与纵向合并。由于 LaTeX 默认按行生成表格,横向合并较为简单,纵向合并则更加复杂,需要额外的宏包支持。

拆分单元格也是一个基本需求,但是在实现上会更加复杂,建议尽量用单元格合并替代单元格拆分。

横向合并

使用 \multicolumn 命令即可完成单元格的横向合并,命令语法如下

1
\multicolumn{<n>}{<alignment>}{<content>}

参数依次为合并的列数,格式以及内容。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
\begin{table}[htbp]
\centering
\begin{tabular}{|c|c|c|}
\hline
1 & 2 & 3(Center) \\
\hline
\multicolumn{2}{|c|}{12} &
\multicolumn{1}{r|}{3(Right)} \\
\hline
1 & \multicolumn{2}{c|}{23} \\
\hline
\end{tabular}
\end{table}

形如 \multicolumn{1}{<column-spec>}{<item>} 的命令没有进行合并,但是可以用来局部调整某一个单元格的列格式。

纵向合并

纵向合并单元格的命令 \multirowmultirow 宏包提供

1
\usepackage{multirow}

命令语法如下

1
\multirow{<nrows>}{<width>}{<content>}

参数依次为合并的行数,宽度以及内容,宽度参数通常填 * 以使用自然宽度,在其它行被合并的单元格位置需要留空。

注意在涉及到纵向合并的位置,\hline 仍然穿越单元格,因此需要使用 \cline 替换。

例如

1
2
3
4
5
6
7
8
9
10
\begin{table}[htbp]
\centering
\begin{tabular}{c|cc}
\hline
\multirow{2}{*}{S} & B1 & C1 \\
\cline{2-3}
& B2 & C2 \\
\hline
\end{tabular}
\end{table}

有一个名称非常类似的宏包 multicol,但是它不是用在表格中,它提供的环境 multicols 用于在正文中创建多栏布局。

三线表

LaTeX 默认的表格线较粗、视觉效果一般,在某些领域更喜欢使用标准的三线表,可以使用 booktabs 宏包

1
\usepackage{booktabs}

此时可以使用几种不同的横线:\toprule(顶线),\midrule(中线),\bottomrule(底线),顶线和底线相比中线更粗。例如

1
2
3
4
5
6
7
8
9
10
11
12
\begin{table}[htbp]
\centering
\caption{Comparison of methods}\label{tab:compare}
\begin{tabular}{lcc}
\toprule
Method & Accuracy & Time (s) \\
\midrule
A & 95.2 & 12.5 \\
B & 93.8 & 10.9 \\
\bottomrule
\end{tabular}
\end{table}

在三线表中,不建议与竖线 | 混用,可以保持排版简洁。

其实这里的粗线和细线也可以通过 \hline[1pt]\hline[0.6pt] 直接实现。

一些例子

下面提供一些更完整的表格例子。(参考 Tips for Writing a Research Paper using LaTeX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
\begin{table}[htbp]
\centering
\caption{A simple table with a header row.}
\label{tab:table1}
\begin{tabular}{*{10}{c}}
\toprule
Data & Size & 2-Exp & 3-Exp & 4-Exp & 5-Exp & 6-Exp & 7-Exp \\
\midrule
A & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
B & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
Ours & $4096\times 2168$ & 2 & 3 & 4 & 6 & 5 & 4 \\
\bottomrule
\end{tabular}
\end{table}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\begin{table}[htbp]
\centering
\caption{A table with multi-column headers.}\label{tab:table2}

\begin{tabular}{*{10}{c}}
\toprule
& & \multicolumn{2}{c}{$6-9$ frames} & \multicolumn{2}{c}{$5-7$ frames} & \multicolumn{2}{c}{$50-200$ frames} \\
Data & Size & 2-Exp & 3-Exp & 2-Exp & 3-Exp & 2-Exp & 3-Exp \\
\midrule
A & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
B & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
Ours & $4096\times 2168$ & 2 & 3 & 4 & 6 & 5 & 4 \\
\bottomrule
\end{tabular}
\end{table}

这个例子使用了 makecell 宏包提供的 \makecell 命令在单元格内换行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% \usepackage{makecell}
\begin{table}[htbp]
\centering
\caption{A table with line break in the header. Line break is useful if the item name is too long.}
\label{tab:table3}
\begin{tabular}{*{10}{c}}
\toprule
& & \multicolumn{3}{c}{$6-9$ frames} & \multicolumn{3}{c}{$5-7$ frames} \\
Data & Size & \makecell{2-Exp \\ Scenes} & \makecell{2-Exp \\ Scenes} & \makecell{2-Exp \\ Scenes} & \makecell{2-Exp \\ Scenes} & \makecell{2-Exp \\ Scenes} & \makecell{2-Exp \\ Scenes} \\
\midrule
A & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
B$^*$ & $1280\times 720$ & 1 & 2 & 3 & 4 & 5 & 4 \\
Ours & $4096\times 2168$ & 2 & 3 & 4 & 6 & 5 & 4 \\
\bottomrule
\end{tabular}

\vspace{1em}
\footnotesize ${^*}$ indicates that method B is trained from scratch.
\end{table}

这个例子使用了 \rowcolor 给表格指定的行加颜色,需要导入额外的宏包 colortbl。(如果直接包起来改颜色,对 & 的解析可能会出错)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% \usepackage{colortbl}
\begin{table}[htbp]
\centering
\caption{A table with parallel lines for grouping and color highlight.}\label{tab:ablation_study}
\begin{tabular}{*{2}{l}||*{2}{c}||*{2}{c}||*{2}{c}}
\toprule
\multicolumn{1}{c}{} & \multicolumn{1}{c||}{} & \multicolumn{2}{c||}{Synthetic Dataset} & \multicolumn{2}{c||}{Static Data} & \multicolumn{2}{c}{Dynamicgt Data} \\
ID & Method & PSNRT & VDP & PSNRT & VDP & PSNRT & VDP \\
\midrule
0 & ANet & 39.25 & 70.81 & 40.62 & 74.51 & 44.43 & 77.74 \\ %
1 & BNet & 39.69 & 70.95 & 37.61 & 75.30 & 43.70 & 78.97 \\
\rowcolor{gray!30}
2 & ANet + BNet & \textbf{40.34} & \textbf{71.79} & \textbf{41.18} & \textbf{76.15} & \textbf{45.46} & \textbf{79.09} \\
\midrule
3 & ANet + BNet w/o C & 39.72 & 71.38 & 40.52 & 74.79 & 45.09 & 78.24 \\ %
4 & ANet + BNet w/o D & 40.03 & 71.66 & 40.80 & 76.12 & 45.17 & 78.99 \\ %
\bottomrule
\end{tabular}
\end{table}

列表

基本使用

无序列表 itemize,默认使用黑点

1
2
3
4
\begin{itemize}
\item First item
\item Second item
\end{itemize}

有序列表 enumerate,默认使用 1. 编号

1
2
3
4
\begin{enumerate}
\item First item
\item Second item
\end{enumerate}

\item 命令可以提供一个可选参数,用于将有序列表的编号或者无序列表的符号替换成自定义内容。

1
2
3
4
\begin{enumerate}
\item A nested item.\label{itref}
\item[*] A starred item.
\end{enumerate}

还可以直接设置为空来删除符号(不影响缩进)

1
2
3
4
\begin{enumerate}
\item[] Item 1
\item[] Item 2.
\end{enumerate}

两种列表支持嵌套,也可以互相嵌套

1
2
3
4
5
6
7
8
\begin{enumerate}
\item First
\begin{itemize}
\item Subitem 1
\item Subitem 2
\end{itemize}
\item Second
\end{enumerate}

在各级列表中,对应的符号和编号样式也有所不同:

  • 无序列表:依次为黑色圆点,-*.
  • 有序列表:依次为 1.(a)i.A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
\begin{multicols}{2}
\begin{itemize}
\item X1
\item X2
\begin{itemize}
\item X11
\item X12 \begin{itemize}
\item X121
\item X122 \begin{itemize}
\item X1221
\item X1222
\end{itemize}
\end{itemize}
\end{itemize}
\end{itemize}
\begin{enumerate}
\item X1
\item X2
\begin{enumerate}
\item X11
\item X12 \begin{enumerate}
\item X121
\item X122 \begin{enumerate}
\item X1221
\item X1222
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{multicols}

补充:

  • 各级无序列表的符号由命令 \labelitemi\labelitemiv 定义,可以简单地重新定义它们;
  • 各级有序列表的符号由命令 \labelenumi\labelenumiv 定义,重新定义这些命令需要用到计数器。

除此之外,还有一个类似的关键字列表,此时 \item[] 的可选参数一般是必选的,并且会被加粗。(description的默认缩进看着非常奇怪,通常需要手动调整)

1
2
3
4
\begin{description}
\item[Enumerate] Numbered list.
\item[Itemize] Non-numbered list.
\end{description}

itemizeenumeratedescription 环境都是基于广义列表环境 list 实现的。

修改列表样式

itemizeenumeratedescription 环境都基于广义列表环境 list 实现,因此它们共享同一套长度参数。通过调整这些内置长度,可以直接控制列表间距,无需引入额外宏包。

使用内置长度命令

涉及的主要长度参数:

参数 含义
\topsep 列表与上下文段落之间的垂直间距(上下各加一次)
\partopsep 当列表前/后有空行时,在 \topsep 基础上额外增加的垂直间距
\itemsep 各项之间的垂直间距
\parsep 同一项内段落之间的垂直间距
\leftmargin 列表整体的左缩进
\rightmargin 列表整体的右缩进
\labelsep 标签与正文之间的水平间距
\labelwidth 标签盒子的宽度
\listparindent 项内段落首行缩进

局部调整 — 在列表环境内部使用 \setlength

1
2
3
4
5
6
7
8
\begin{itemize}
\setlength{\itemsep}{0.8em}
\setlength{\parsep}{0pt}
\setlength{\topsep}{0.5em}
\item 第一项
\item 第二项
\item 第三项
\end{itemize}

全局调整 — 在导言区设置,对所有列表生效:

1
2
3
4
5
% 调整列表间距
\setlength{\itemsep}{0.5em}
\setlength{\parsep}{0pt}
\setlength{\topsep}{0.3em plus 0.1em minus 0.1em}
\setlength{\partopsep}{0pt}

注意:导言区的 \setlength 会影响 itemizeenumeratedescription,因为三者共享同一套长度参数。

嵌套列表的左缩进由 \leftmargini\leftmarginvi 分别控制一到六级:

1
2
3
\setlength{\leftmargini}{2em}
\setlength{\leftmarginii}{1.5em}
\setlength{\leftmarginiii}{1em}

使用 enumitem 宏包

如果需要更精细地控制标签样式(如修改编号格式)或对不同列表类型设置不同间距,enumitem 宏包提供了更方便的 key=value 接口。

1
\usepackage{enumitem}

最基础的样式需求是修改列表编号和符号,可以通过 label=... 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
\begin{enumerate}[label=\arabic*.] % 1.
\item Item 1
\item Item 2
\end{enumerate}

\begin{enumerate}[label=\alph*.] % a.
\item Item 1
\item Item 2
\end{enumerate}

\begin{enumerate}[label=\roman*.] % i.
\item Item 1
\item Item 2
\end{enumerate}

\begin{itemize}[label=\textbullet] % •
\item Item 1
\item Item 2
\end{itemize}

\begin{itemize}[label=--] % –
\item Item 1
\item Item 2
\end{itemize}

\begin{itemize}[label=\textasteriskcentered] % *
\item Item 1
\item Item 2
\end{itemize}

如果给 enumitem 宏包加上 shortlabels 选项,就可以更简单地实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
\begin{enumerate}[1.]
\item Item 1
\item Item 2
\end{enumerate}

\begin{enumerate}[(a)]
\item Item 1
\item Item 2
\end{enumerate}

\begin{enumerate}[i.]
\item Item 1
\item Item 2
\end{enumerate}

\begin{itemize}[-]
\item Item 1
\item Item 2
\end{itemize}

\begin{itemize}[*]
\item Item 1
\item Item 2
\end{itemize}

与缩进和空格相关的参数主要包括:

  • leftmargin 列表整体的左缩进
    • leftmargin=* 自动计算缩进,使列表与父环境左对齐,而不是固定缩进
  • topsep 列表与上下文段落的垂直间距
  • itemsep 每项之间的垂直间距

例如移除左缩进:

1
2
3
4
5
\begin{enumerate}[leftmargin=*]
\item Item 1
\item Item 2
\item Item 3
\end{enumerate}

移除各项之间的垂直间距:

1
2
3
4
5
\begin{enumerate}[itemsep=0pt]
\item Item 1
\item Item 2
\item Item 3
\end{enumerate}

对于嵌套列表,可以为每层嵌套单独调整 leftmargin,避免缩进过深或过浅:

1
2
3
4
5
6
7
8
\begin{enumerate}
\item First
\begin{itemize}[leftmargin=1.5em]
\item Subitem 1
\item Subitem 2
\end{itemize}
\item Second
\end{enumerate}

可以使用 \setlist 命令对列表样式进行全局配置:

1
2
3
4
\usepackage{enumitem}

\setlist[itemize]{label=--, leftmargin=2em, itemsep=0.5em}
\setlist[enumerate]{label=\arabic*., leftmargin=2em, itemsep=0.3em}

算法环境 algorithm2e

介绍

在 LaTeX 中使用伪代码来描述算法是常见的需求,LaTeX 其实有很多类似名称的宏包,简单辨析一下:(参考 latex 中 algorithm、algorithmic、algorithmicx、algorithm2e 的区别

  • algorithm 用来封装算法:给算法加上标题(caption)和标签(label),方便进行索引;
  • algorithmic 相当于算法的内容物;
  • algorithmicx 相当于 algorithmic 的升级版;
  • algpseudocodealgorithmicx 的一种呈现方式,完整包含了algorithmicx
  • algorithm2ealgorithmicxalgorithmic 类似,也是用来描述算法的;但是其语法不如 algorithmicx 直白。

总得来说,通常有两条路线可以选择:

  1. algorithm2e宏包搞定
  2. algpseudocodealgorithmic等撰写算法本身,再用algorithm包给算法加标题

本文主要考虑第一个方式——使用algorithm2e宏包。

在导入algorithm2e宏包时,通常会顺便加上一些选项,例如

1
2
3
4
\usepackage[ruled,linesnumbered,noline]{algorithm2e}
% ruled 上下添加横线,类似于三线表,此时标题在上面
% linesnumbered 显示行数
% noline 关闭默认体现层级的竖线

算法环境的主体框架如下,通常会添加标题(caption)和标签(label

1
2
3
4
5
6
\begin{algorithm}
\caption{XXX}\label{alg1}

...

\end{algorithm}

一个简单的例子:欧几里得算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
\documentclass{article}
\usepackage[ruled,linesnumbered,noline]{algorithm2e}

\begin{document}

\begin{algorithm}
\caption{Euclid's algorithm}
\KwData{Two nonnegative integers $a$ and $b$}
\KwResult{Their greatest common divisor $d = \gcd(a, b)$}
\While{$b \neq 0$}{
$r \leftarrow a \bmod b$\;
$a \leftarrow b$\;
$b \leftarrow r$\;
}
$d \leftarrow a$\;
\end{algorithm}

\end{document}

在导入时使用[ruled,linesnumbered,noline]选项,得到的效果如下图

与之相比,使用默认选项的效果就差很多,并不符合文献中的主流风格

基本使用

以欧几里得算法为例

1
2
3
4
5
6
7
8
9
10
11
\begin{algorithm}
\caption{Euclid's algorithm}
\KwData{Two nonnegative integers $a$ and $b$}
\KwResult{Their greatest common divisor $d = \gcd(a, b)$}
\While{$b \neq 0$}{
$r \leftarrow a \bmod b$\;
$a \leftarrow b$\;
$b \leftarrow r$\;
}
$d \leftarrow a$\;
\end{algorithm}

在算法环境中,每一行语句可以使用\;结尾,这会在文本中加上分号结尾并换行,还可以使用\\强行换行。
除此之外,下面的某些固定语法结构也会导致换行。
算法内部需要数学表达式时,仍然需要$$等来创建数学环境。

算法通常需要使用下面这些预定义宏:

  • IO:
    • 输入:\KwIn{<input>}
    • 数据:\KwData{<input>}
    • 输出:\KwOut{<output>}
    • 结果:\KwResult{<output>}
  • 基础:
    • to: \KwTo
    • 返回值:\KeRet{<value>}或等效的\Return{<value>}
  • 循环:包括下面几种形式,其中含l-前缀的版本是行内形式,即内部不产生换行(但结尾仍然有换行)
1
2
3
4
5
6
7
8
9
\For{<condition>}{<text loop>}
\While{<condition>}{<text loop>}
\ForEach{<condition>}{<text loop>}
\ForAll{<condition>}{<text loop>}

\lFor{<condition>}{<text loop>}
\lWhile{<condition>}{<text loop>}
\lForEach{<condition>}{<text loop>}
\lForAll{<condition>}{<text loop>}
  • 条件:包括下面几种形式,默认形式会产生换行并使用 end 结尾;含l-前缀的版本是行内形式,即内部不产生换行(但结尾仍然有换行);含e-前缀的 eIf 自带真假两个分支;含u-前缀的版本是未完成形式,即结尾不含 end,需要搭配其他命令来收尾
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\If{<condition>}{<then block>}
\ElseIf{<elseif block>}{<then block>}
\Else{<else block>}

\lIf{<condition>}{<then block>}
\lElseIf{<elseif block>}{<then block>}
\lElse{<else block>}

\uIf{<condition>}{<then block>}
\uElseIf{<elseif block>}{<then block>}
\uElse{<else block>}

\eIf{<condition>}{<then block>}{<else block>}

\leIf{<condition>}{<then block>}{<else block>}
  • 注释:默认支持两类注释,即tcc(C 语言风格/**/)和tcp(C++风格//)注释,有几个选项会调整注释的细节,这里略去
1
2
3
4
5
6
7
8
9
10
11
12
13
\tcc{<comment>}
\tcc*{<comment>}
\tcc*[r]{<comment>}
\tcc*[l]{<comment>}
\tcc*[h]{<comment>}
\tcc*[f]{<comment>}

\tcp{<comment>}
\tcp*{<comment>}
\tcp*[r]{<comment>}
\tcp*[l]{<comment>}
\tcp*[h]{<comment>}
\tcp*[f]{<comment>}

对于循环和条件结构的呈现,还涉及到如下几个选项:

  • lined:伪代码的 start-end 之间用竖线相连
  • vlined:伪代码的 start-end 之间用竖折线相连,其中折线代替了 end 的作用
  • noline:伪代码的 start-end 之间没有线相连

这几个选项既可以在宏包选项中设置,也可以使用下面的命令设置

1
2
3
\SetAlgoLined
\SetAlgoVlined
\SetAlgoNoline

在循环和条件结构中,都支持加上括号包裹的注释选项,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
\lIf(\tcc*[h]{lif comment}){test}{
text
}
\uIf(\tcc*[f]{uif comment}){test}{
then text\;
}
\uElseIf(\tcc*[f]{comment}){test}{
elseif text\;
}
\lElseIf(\tcc*[h]{comment}){test}{
text
}
\lElse(\tcc*[f]{comment}){text}

宏包还支持自定义一些宏,例如下面定义了与 IO 宏类似的一个命令\KwPara{<input>},代表算法需要的各种细节参数

1
2
3
\SetKwInput{KwPara}{Parameter}

\KwPara{m,n,$\varepsilon$}

除了这个宏包之外,还可以使用其他方式来实现,例如导入algorithmalgpseudocode这两个宏包,本文暂不讨论具体细节,不过可以明确的是,它的命令风格与algorithm2e是截然不同的。

抄录环境 verbatim

LaTeX 直接提供verbatim抄录环境,在其中以等宽字体按照原样排版代码,回车和空格都是正常的换行和空位的作用,缩进也是原样保留的。使用示例如下

1
2
3
4
5
6
7
8
\begin{verbatim}
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
\end{verbatim}

效果如下图

注意这不是代码环境,因为它只是忠实地保持原样输出,并没有提供常见的语法高亮功能。
还有与之类似的verbatim*环境,它更进一步将空格显示为

与之类似的,还有展示行内抄录片段或关键字的\verb命令

1
\verb<delim><code><delim>

与常见的命令不同,\verb需要提供自定义的分界符delim来标明代码的前后分界位置,要求前后分界符必须一致,除字母、空格或星号外,可任意选择不与代码自身冲突的符号(习惯上可以使用|符号),例如

1
2
3
4
5
\verb|a\ b|         % 使用|作为分界符 a\ b

\verb+(a || b)+ % 使用+作为分界符 (a || b)

\verb+\ldots+ % 使用+作为分界符 \ldots

代码环境 listings

介绍

这里指的是展示编程语言的源代码片段的环境,与前面的算法环境/抄录环境都是不一样的。

listings宏包是一个功能强大也非常复杂的宏包,用于提供特定编程语言的语法高亮。

1
\usepackage{listings}

下面是最简单的例子,在文档中展示了一段 Python 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
\documentclass{article}
\usepackage{listings}

\begin{document}

\begin{lstlisting}[language=Python, caption=Demo]
def helloworld():
print("Hello, world!")

helloworld()
\end{lstlisting}

\end{document}

效果如下图(具体效果可能和不同的编译器有关,下图是使用xelatex编译的结果)

除了listingsminted宏包是另一种常见语法高亮方案,它基于 Python 提供的支持进行语法高亮,在编译时需要传入特殊的选项-shell-escape,暂略。

基本使用

listings宏包最主要的用法是使用lstlisting环境导入代码片段

1
2
3
\begin{lstlisting}
<codes>
\end{lstlisting}

可以加上一些选项,例如指定语言

1
2
3
\begin{lstlisting}[language=Python]
<codes>
\end{lstlisting}

提供的语言类型会被用于识别关键字、字符串、注释等,进而影响具体的显示效果。

listings宏包还支持从源代码文件中直接导入代码,需要使用专门的\lstinputlisting命令

1
\lstinputlisting[language=Python]{main.py}

\lstinputlisting命令默认会导入所有代码,可以设置起止行号来导入源文件中的部分片段

1
\lstinputlisting[language=Python, firstline=2, lastline=12]{main.py}

补充:\lstlistoflistings命令会将所有添加caption的代码片段生成代码目录。

除此之外,listings宏包还提供\lstinline命令用于行内代码片段展示:\lstinline|<codes>|
\verb命令类似,它的分界符可以是任意的,从而避免与代码中的字符冲突,例如

1
2
3
\lstinline!var i:integer;!

\lstinline|int x=1;|

配置

listings宏包默认的显示效果很丑,需要经过一番配置才能达到美观的语法高亮显示效果。
配置既可以在具体的环境开头指定,也可以在导言区进行全局默认设置。

对于具体环境的配置通过可选参数给出,例如

1
2
3
4
5
6
7
8
9
10
11
\begin{lstlisting}[
language=Python, % 语言
numbers=left, % 行号显示位置
firstnumber=1 % 行号开始
]
# Python
def hello():
print("Hello, world!")

hello()
\end{lstlisting}

在导言区进行全局默认配置,也就是修改默认样式,例如

1
2
3
4
5
6
7
8
\lstset{
language=Python, % 设置语言
columns = fixed, % 列距排版
basicstyle = \linespread{0.8} \ttfamily, % 设置行距,字体
numbers = left, % 行号显示设置
frame = single, % 背景边框
showstringspaces = false, % 字符串中的空格显示
}

此时就不需要在每个环境中进行配置了。

除此之外,还可以重新定义一套新的样式(而非修改默认样式),例如针对特定的语言进行配置

1
2
3
\lstdefinestyle{cppStyle}{
...
}

对自定义样式的使用通过style选项指定

1
2
3
4
5
6
7
8
\begin{lstlisting}[style=cppStyle]
#include <iostream>

int main() {
std::cout << "Hello, world!\n";
return 0;
}
\end{lstlisting}

还可以在导言区使用下面的命令将新定义的样式设置为默认样式

1
\lstset{style=cppStyle}

在更丰富的配置中通常会搭配使用xcolor宏包,定义新的颜色用于代码高亮,例如

1
2
3
4
5
6
7
\usepackage{xcolor}

\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}

\definecolor{epubblue}{RGB}{1,126,218}

颜色的使用例如\color{gray}。注意上面的小写 rgb 接受的参数为 0-1 的小数值,而大写 RGB 接受的是 0-256 的整数值。

下面是listings宏包支持的常见配置选项:

  • 语言设置:language=Python,C++,支持多个语言,注意 C++的名称要用 C++而非 Cpp
  • 基本样式设置basicstyle = \ttfamliy,这是指定等宽字体(符合编程习惯)
  • 样式:主要是颜色和字体设置,针对关键词,字符串和注释
    • 关键字样式:keywordstyle=\bfseries \color[RGB]{40,40,255},通常指定一个颜色
    • 注释样式:commentstyle=\color[RGB]{0,96,96}, 通常指定一个颜色
    • 字符串样式:stringstyle=\color[RGB]{128,0,0}, 通常指定一个颜色
    • 行号样式:numberstyle=\footnotesize,这可以让行号的字体更小一点
    • 标识符样式:identifierstyle=\color{black},标识符的颜色字体等
  • 补充关键词:morekeywords={eg1,eg2},这可以加入自定义关键词,默认的不太全
  • 自动换行:breaklines=true,建议,否则过长的行会直接截断!
  • 行号显示:
    • 是否显示行号:numbers=left,支持 left/right/none,默认为 none 不显示
    • 间隔多少行显示行号:stepnumber=5
    • 行号起始:firstnumber=10,设置为 last 则继承上一个代码环境的行号
  • 列间距设置:columns=flexible,让不同列之间的距离自适应,反之可以使用fixed设置固定距离
  • 字符串中的空格显示:showstringspaces=false,否则默认会对字符串内的空格显示下划线
  • tab 与缩进:
    • 突出显示 tab:showtabs=true,会将 tab 显示为长的下划线,默认不显示(只展示连续空格)
    • tab 长度:tabsize=8,默认长度为 8 个空格
  • 边框:frame=single,single 显示单边框,shadowbox 为阴影框,默认是 none 无边框
  • 背景颜色:backgroundcolor=xxx
  • 代码块标记:name=xxx,同名的代码块行号会自动延续
  • 代码块显示名称:caption=Name,还可以指定名称的显示位置(默认在顶部),例如captionpos=b改在底部,caption 会自动编号,如果不需要编号,可以使用title=xxx,如果同时出现则会显示后设置的项
  • 忽略部分字符以支持 latex 命令:escapeinside={\%*}{*)}

下面是一份参考的语法高亮配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
\usepackage{listings}
\usepackage{xcolor}

\lstdefinestyle{simpleStyle}{
basicstyle=\ttfamily\small, % 设置字体族
breaklines=true, % 自动换行
keywordstyle=\color{blue}, % 关键字样式
identifierstyle=\color{black}, % 标识符样式
stringstyle=\color{violet}, % 字符串样式
commentstyle=\color[RGB]{34,139,34}, % 注释样式
showstringspaces=false, % 不显示字符串中的空格
numbers=left, % 显示行号在左边
numbersep=2em, % 设置行号的具体位置
numberstyle=\footnotesize, % 缩小行号
frame=single, % 边框
framesep=1em, % 设置代码与边框的距离
}

\lstset{style=simpleStyle}

这里并没有指定语言,因此每一个代码块必须要指定语言才能有更好的显示效果。

下面依次是 MATLAB,Python,C 的使用示例以及对应的显示效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
\begin{lstlisting}[language=Matlab, caption=MATLAB Example]
% Call function to compute first 10 terms
fibonacci(10);

function fibonacci(n)
% Calculate the first n Fibonacci numbers
fib = zeros(1, n); % Initialize array
fib(1) = 0; % First term
if n > 1
fib(2) = 1; % Second term
end

for i = 3:n
fib(i) = fib(i-1) + fib(i-2); % Current term
end

% Display results
fprintf('First %d Fibonacci numbers:\n', n);
disp(fib);
end
\end{lstlisting}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
\begin{lstlisting}[language=Python, caption=Python Example]
def fibonacci(n):
"""Calculate the Fibonacci sequence up to n."""
fib = [0, 1] # Initialize the list
while len(fib) < n:
fib.append(fib[-1] + fib[-2]) # Append the next Fibonacci number
return fib

# Get user input
num = int(input("Enter the number of terms: "))
result = fibonacci(num)

# Display the result
print(f"The first {num} Fibonacci numbers are: {result}")

\end{lstlisting}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
\begin{lstlisting}[language=C, caption=C Example]
#include <stdio.h>

void fibonacci(int n) {
// Calculate Fibonacci numbers up to n
int fib[n];
fib[0] = 0;
fib[1] = 1;

for (int i = 2; i < n; i++) {
fib[i] = fib[i - 1] + fib[i - 2]; // Calculate the next Fibonacci number
}

// Print the results
printf("The first %d Fibonacci numbers are:\n", n);
for (int i = 0; i < n; i++) {
printf("%d ", fib[i]);
}
printf("\n");
}
\end{lstlisting}

hyperref 宏包使用

使用 hyperref 宏包可以定制交叉引用和超链接样式。

1
\usepackage{hyperref}

这个宏包容易和其它宏包产生冲突,建议将其放在靠后的位置导入,否则可能导致跳转错误。

可以用下面的命令生成可点击的超链接

1
2
\url{url}
\url{https://www.baidu.com}

可以在添加超链接时,设置显示的文本内容

1
2
\href{url}{text}
\href{https://www.baidu.com}{Baidu}

可以用下面的命令设置样式

1
\hypersetup{colorlinks=true,linkcolor=,urlcolor=cyan}

也可以在宏包加载时直接传递样式选项

1
\usepackage[colorlinks=true,linkcolor=,urlcolor=cyan]{hyperref}

解释一下几个常见的选项:

选项 含义 说明
colorlinks 是否用颜色标记链接(若为 false,则显示彩色方框) 建议设为 true,避免方框,默认 false
linkcolor 内部链接颜色(章节、图表、公式等引用) 控制 \ref\autoref 等颜色
citecolor 文献引用颜色 控制 \cite 链接颜色
urlcolor URL 链接颜色 控制 \url\href 等外部链接
filecolor 文件链接颜色 用于指向本地文件的链接
hidelinks 隐藏所有颜色与边框 适合正式论文或投稿版本

hyperref 还提供了 \autoref 命令,它会在引用编号前自动加上类型名称,例如 \autoref{fig:demo} 输出 “Figure 1”,\autoref{sec:intro} 输出 “section 2”。相比 \ref 只输出编号,\autoref 更适合在句首使用或需要明确引用类型的场合。这些类型名称默认是英文的,可以通过 \renewcommand 重定义(如 \renewcommand{\figureautorefname}{图})。

需要特别注意的是:如果在章节标题(例如 \section{...})中使用复杂数学符号(例如 $\mathbb{S}^2$),可能导致编译卡死。

例如

1
\section{Three Spatial Dimensions with Directions on $\mathbb{S}^2$}

编译过程卡死的原因不是标题不支持,而是 PDF 书签不支持,hyperref 宏包会自动生成 PDF 标签。
解决方案:尽量避免在各级标题中使用数学符号;如果必须要在标题中使用复杂数学符号,可以用 hyperref 宏包提供的 \texorpdfstring 命令,原理很简单——给复杂数学公式提供一个简单文本的替代品,hyperref 在生成书签时会使用替代品。

例如

1
\section{Three Spatial Dimensions with Directions on \texorpdfstring{$\mathbb{S}^2$}{S2}}

此时在正文和目录中仍然会显示复杂数学符号,但是在 PDF 书签中会显示更简单的替代文本。

水印与标记

PDF 水印

给 PDF 文件加上水印是一个常见的需求,比如标记文档的来源,或者标记当前版本为草稿等。

可以使用 draftwatermark 宏包实现

1
\usepackage{draftwatermark}

导入这个宏包就会默认在每一页的中央添加倾斜的水印 DRAFT

测试发现 pdflatex 进行编译可能无法添加水印,或者水印显示异常,因此最好使用 xelatex。

可以调整水印的样式(内容,颜色,大小等)

1
\DraftwatermarkOptions{text={Draft},color={[gray]{0.9}},scale=0.5}

可以在水印中添加编译时间以区别不同版本

1
2
3
4
\usepackage{datetime2}
\usepackage[firstpageonly]{draftwatermark}

\DraftwatermarkOptions{text={Update: \DTMnow},color={[gray]{0.95}},scale=0.3}

也可以在导入宏包时全部作为参数传递

1
2
\usepackage{datetime2}
\usepackage[firstpageonly,text={Update: \DTMnow},color={[gray]{0.95}},scale=0.3]{draftwatermark}

注意:

  • 默认给所有页加水印,导入宏包时可以加参数 firstpageonly 只在第一页添加水印;
  • 水印的文字只会在页面中央出现一次,不会循环出现;
  • 水印不会遮盖图片,图片会出现在水印的上层。

多人批注标记

在多人协作编辑 LaTeX 文档时,可以给每个人定义一个专属的批注命令,便于区分。

例如

1
2
\newcommand{\li}[1]{{\color{red}{[(Li): #1]}}}
\newcommand{\wang}[1]{{\color{blue}{[(Wang): #1]}}}

在正文中使用 \li{xxx} 即可在添加段内批注。

还可以使用 \marginpar{xxx} 添加页边批注,或者基于下面的 todonotes 宏包进行封装。

待办标记

LaTeX 有一个 todonotes 宏包,可以用来进行一些标注

1
\usepackage{todonotes}

在指定位置使用\todo{xxx}即可在页边加上备注,并且使用横线指向对应位置。
它还提供了一个命令可以生成默认图片在排版中起到占位的效果。

1
\missingfigure{xxx.}

可以给\todo{xxx}或者宏包传递颜色参数,例如

1
2
3
\usepackage[color=green]{todonotes}

\todo[color=green]{xxx}

\todo命令最好直接放在正文中,直接放在一些特殊环境中(例如图表环境的 caption,定理环境等)容易导致编译错误,可以加上 inline 选项,例如

1
2
3
4
5
\begin{figure}[htbp]
\centering
\includegraphics{demo.png}
\caption{Title \todo[inline]{xxx.}}
\end{figure}

传递 disable 选项可以直接全局注释所有的标注

1
\usepackage[disable]{todonotes}

注意:todonotes 的颜色支持依赖 xcolor 包,如果需要在导入 xcolor 包时传递选项,最好在 todonotes 之前手动导入 xcolor 包。

特殊页面需求

护眼色背景

对于非正式的笔记中,我们可以不选择使用标准的白色背景,而是改成护眼色,可以使用 xcolor 宏包的 \pagecolor 命令实现,例如

1
\pagecolor{LimeGreen!15}

还有几种取自 ElegantNote 的护眼色方案可以参考

1
2
3
4
5
6
7
8
\definecolor{geyecolor}{RGB}{199,237,204}
\pagecolor{geyecolor}

\definecolor{geyecolor}{RGB}{251,250,248}
\pagecolor{geyecolor}

\definecolor{geyecolor}{RGB}{250,237,225}
\pagecolor{geyecolor}

特殊页面尺寸

下面是一种适合 iPad 竖屏阅读的页面尺寸

1
2
3
4
5
6
\usepackage{geometry}
\geometry{
paperwidth=7in,
paperheight=10in,
includefoot,
margin=8mm}

下面是一个横版的 A4 纸布局尺寸,可以用于在大屏幕中分享,但又不适合 beamer 的情景

1
2
3
4
5
6
7
8
9
10
\documentclass[17pt]{extarticle}
\geometry{
a4paper,
landscape,
includefoot,
margin=14mm}
\usepackage{setspace}
\setstretch{1.2} % 设置行距
\setlength{\parindent}{0pt} % 取消缩进
\renewcommand{\familydefault}{\sfdefault} % 设置无衬线字体

这里对远距离的屏幕阅读做了一些专门的优化:使用大字体以及支持大字体的 extarticle 文档类,调整行距和缩进,设置无衬线字体。