\chapter{幻灯片}

现在你大概已经领略甚至可能掌握了 \CONTEXT\ 常用的排版元素，若依然使用 Microsoft PowerPoint 或 WPS 之类的软件制作幻灯片则甚为可惜。其实，只需再掌握寥寥几条排版命令便可以用 \CONTEXT\ 制作出独具风格的幻灯片了。

\section{纸面尺寸}

纸面尺寸是页面的打印尺寸。至此为止，本文档之前所有的示例，在 \type{TEXpage} 环境里的，纸面尺寸取决于文档内容的多少，而在 \type{text} 环境里的，纸面尺寸默认是 A4，即 $21\,{\rm cm}\times 29.7\,{\rm cm}$。如果你需要将纸面尺寸换成 A5，只需在样式文件中作以下设定\cmdindex{setuppapersize}

\cmdindex{setuppapersize}
\starttyping[option=TEX]
\setuppapersize[A5]
\stoptyping

制作幻灯片通常不需要太大的纸面尺寸。\CONTEXT\ 提供了 S4 尺寸（$400\,{\rm pt}\times 300\,{\rm pt}$），可将其作为幻灯片的纸面尺寸，或者你根据自身需求定义一个纸面尺寸来用\cmdindex{definepapersize}，例如

\starttyping[option=TEX]
\definepapersize[slidesize][width=640pt,height=480pt]
\setuppapersize[slidesize]
\stoptyping

实际上，纸面尺寸仅对排版结果的打印很重要，倘若只是在计算机（或投影仪）屏幕上观看排版结果，我们总是可以通过调整正文字体大小去应对过大或过小的纸面尺寸，但是纸面尺寸的宽高比例，对于屏幕非常重要。通常，幻灯片的宽高比应当与屏幕的分辨率相适应为最佳。例如，我的屏幕分辨率是 $1600\times 900$，那么我要制作的幻灯片页面的宽高比也应当是 $16:9$，故而纸面尺寸可设定为

\cmdindex{definepapersize}
\starttyping[option=TEX]
\definepapersize[slidesize][width=640pt,height=360pt]
\setuppapersize[slidesize]
\stoptyping

现在，我们可以制作幻灯片的最原始的形式了，见下例。

\starttyping[option=TEX]
\usemodule[visual]
\definepapersize[slidesize][width=640pt,height=360pt]
\setuppapersize[slidesize]

\starttext
\title{\fakewords{3}{5}}
\fakewords{50}{100}
\stoptext
\stoptyping
\midaligned{\externalfigure[12/slides-1.pdf][width=.6\textwidth,frame=on]}

\section{页面布局}

在 \type{text} 环境之前添加以下代码：

\starttyping[option=TEX]
\showframe
\stoptyping

\noindent 可在页面上显示当前的页面布局，结果如图 \in[12-layout-1] 所示。可根据图 \in[ConTeXt-layout] 理解页面布局中各区域名称和尺寸参数名称。

\placefigure[here][12-layout-1]{\CONTEXT\ 默认的页面布局}{\externalfigure[12/layout-1.pdf][width=.6\textwidth]}

\placefigure[here][ConTeXt-layout]{页面布局注解}{\externalfigure[12/ConTeXt-layout.svg][width=.8\textwidth]}

使用 \type{\setlayout}\cmdindex{setlayout} 可对各区域尺寸进行调整，例如让版心居中，即图 \in[ConTeXt-layout] 所示的 \type{width} 和 \type{textheight} 确定的区域居中，因为在默认情况下，它有些偏左。我们已经知道，页面的横向尺寸是 640pt，按以下设定即可令版心居中。

\cmdindex{setuplayout}
\starttyping[option=TEX]
\setuplayout
  [leftedge=0pt,leftedgedistance=0pt,
   leftmargin=80pt,leftmargindistance=10pt,
   backspace=90pt,
   rightedge=0pt,rightedgedistance=0pt,
   rightmargin=80pt,rightmargindistance=10pt,
   width=460pt]
\stoptyping

\noindent 上述设定，实现了页面布局中页面总宽度值 640 pt 的分配，但是要注意一点，\type{backspace} 的值等于 4 个以 \type{left} 为前缀的参数值之和，虽然在设定了它的各个分量后，但 \CONTEXT\ 在遇到默认的 \type{backspace} 值与实际的 \type{left...} 参数值之和不符时，会根据 \type{backspace} 值进行页面布局。倘若我们不关心 \type{left...} 参数，即 \CONTEXT\ 默认对页面左侧留白区域默认如何分配，仅需要让 \CONTEXT\ 知道 \type{backspace=90pt}，则上述代码可简化为

\starttyping[option=TEX]
\setuplayout
  [backspace=90pt,
   rightedge=0pt,rightedgedistance=0pt,
   rightmargin=80pt,rightmargindistance=10pt,
   width=460pt]
\stoptyping

\noindent 还可以进一步简化，因为 \CONTEXT\ 对 \type{rightedge} 和 \type{rightedgedistance} 赋予的默认值原本就是 0，因此有

\starttyping[option=TEX]
\setuplayout
  [backspace=90pt,
   rightmargin=80pt,rightmargindistance=10pt,
   width=460pt]
\stoptyping

如果只关心版心的横向居中问题，并不关心左右留白区域的尺寸，最为简单的布局方式是

\starttyping[option=TEX]
\setuplayout[width=middle]
\stoptyping

以上设置的是页面横向布局。对于纵向布局，存在与 \type{backspace} 类似的问题，即 \type{topspace} 的设定。\type{topspace} 的值是 \type{top} + \type{topdistance}，但是在 \type{\setuplayout} 中只对后者进行设定是无效的，必须先设定 \type{topspace}，然后再将其值分配给 \type{top} 和 \type{topdistance}，或让直接将 \type{height} 设为 \type{middle}，让 \CONTEXT\ 自动确定纵向布局。以下纵向参数

\starttyping[option=TEX]
height=middle,topspace=0pt,bottom=0pt,footer=40pt
\stoptyping

\noindent 达到的效果是，页面纵向居中，去除页面顶部和底部留白以节省空间，脚注区域保留。

下面给出一个完整的页面布局设定：

\starttyping[option=TEX]
\setuplayout[width=middle,height=middle,topspace=0pt,bottom=0pt,footer=40pt]
\stoptyping
\midaligned{\externalfigure[12/layout-2.pdf][width=.6\textwidth,frame=on]}

在完成页面布局设定后，别忘记去掉 \type{text} 环境之前的 \type{\showframe} 语句。此外，我建议你在 \type{text} 环境里动手试验一番 \type{\showlayout}。

\section[slide-fonts]{字体}

在 \CONTEXT\ 使用汉字字体，对此估计你已经颇为熟悉了。在幻灯片中，字体可设定为

\starttyping[option=TEX]
\definefallbackfamily
  [myfonts][ss][latinmodernsans]
  [range={0x0000-0x0400},force=yes]
\definefontfamily[myfonts][ss][simhei][bf=simhei,it=kaiti,bi=simhei]
\setscript[hanzi]
\setupbodyfont[myfonts,ss,16pt]
\stoptyping

\noindent 幻灯片所用字体，通常以无衬线字体为主，因为这类字体在屏幕上较为醒目。至于衬线字体和等宽字体，可依情况而定。

\section[regular-style]{常规样式}

幻灯片通常不需要页码，即使需要页码，默认的页码出现的位置和字号皆不合适，故而需消除 \CONTEXT\ 默认在页面顶部设置的页码：

\starttyping[option=TEX]
\setuppagenumbering[location=]
\stoptyping

行间距可设为正文字号的 1.75 倍：

\starttyping[option=TEX]
\setupinterlinespace[line=1.75\bodyfontsize]
\stoptyping

下例设置了列表的第 1 级样式，具体为 (1) 将 \in[drawing-sym] 节实现的列表项符号作为默认列表项符号，只是正方形的阴影颜色略加修改；(2) 消除列表项的间距；（3） 在列表项的符号和内容之间插入 .5em 的间距；(4) 让列表前后各空 1/4 行。

\starttyping[option=MP]
\startuseMPgraphic{square}
numeric u; path p;
u := BodyFontSize; 
p := fullsquare scaled .8u;
fill p shifted (.2u, -.2u) withcolor .75white;
fill p withcolor .5[blue, white];
\stopuseMPgraphic
\stoptyping
\starttyping[option=TEX]
\definesymbol[10][{\lower.2\bodyfontsize\hbox{\useMPgraphic{square}}}]
\setupitemize[1] % 列表第 1 级样式
             [10,packed]
             [distance=.5em,
               before={\blank[quarterline]},
               after={\blank[quarterline]}]
\stoptyping
\noindent 注意，上述代码中的 \type{.75white} 等效于 rgb 三元组 \type{(0.75, 0.75, 0.75)}。另外，若需要二级和三级列表，只需将 \tex{setupitemize} 的第 1 个参数换成 2 或 3，然后参照上例设定列表样式。

将幻灯片一级标题设置为居中对齐，并设置字号和颜色，且令其前后各空半行：

\starttyping[option=TEX]
\setuphead
  [title,chapter]
  [align=center,
    style=\ssb,
    color=darkred,
    before={\blank[halfline]},
    after={\blank[halfline]}]
\stoptyping

可以在 \type{text} 环境里随便写点什么，以察验上述设定是否起效，例如：

\starttyping[option=TEX]
\starttext
\startbuffer[foo]
\chapter{蒙卦}
亨。匪我求童蒙，童蒙求我；初筮告，再三渎，渎则不告。利贞。
\startitemize
\item 初六，发蒙，利用刑人，用说桎梏；以往吝。
\item 九二，包蒙，吉。纳妇，吉；子克家。
\item 六三，勿用取女，见金夫，不有躬，无攸利。
\item 六四，困蒙，吝。
\item 六五，童蒙，吉。
\item 上九，击蒙，不利为寇，利御寇。
\stopitemize
\stopbuffer
\dorecurse{3}{\getbuffer[foo]}
\stoptext
\stoptyping
\midaligned{\externalfigure[12/slides-2.pdf][width=.625\textwidth,frame=on]}

\noindent 上述代码使用了 \CONTEXT\ 的 \type{buffer} 环境\index[buffer]{\type{buffer} 环境}。所谓 \type{buffer}，是可以设定名字的缓存，它可以包含 \CONTEXT\ 排版代码。\type{\getbuffer} 用于获取缓存内容。

以下设定，可将标题的数字编号更改为中文编号，且将编号样式设定为 \type{inmargin}，表示编号不参与居中对齐，只有标题内容参与对齐。

\starttyping[option=TEX]
\setuphead[chapter][conversion=chinesenumerals,alternative=inmargin]
\stoptyping
\midaligned{\externalfigure[12/slides-3.pdf][width=.625\textwidth,frame=on]}

\section[footer]{页脚}

在 \in[regular-style] 节中，我关闭了 \CONTEXT\ 好意提供的页码，但并非不需要页码，而是我期望页码能出现在页面的右下角，且除以总页数，以便清楚幻灯片的进度。

\CONTEXT\ 提供了 \type{\setupfootertexts} 命令\cmdindex{setupfootertexts}，可以在页脚左、右区域放入文字、盒子或图形等内容，同时提供了 \type{\setupfooter} 用于设定页脚区域的文字样式。另外，\type{\userpagenumber}\cmdindex{userpagenumber} 和 \type{\lastuserpage}\cmdindex{lastuserpage} 可分别用于获取当前页的页码和最后一页的页码。基于这些命令，便可实现能够表示进度的页码，例如

\cmdindex{setupfootertexts}
\starttyping[option=TEX]
\setupfooter[style=small,color=darkred]
% 令页脚左侧区域为空，右侧区域放置用于表示进度的页码
\setupfootertexts[margin][][\hss\userpagenumber/\lastuserpage]
\stoptyping

\noindent 结果如图 \in[页码进度] 所示。
\placefigure[here][页码进度]{第 4 页幻灯片}{\externalfigure[12/slides-4.pdf][page=4,width=.6\textwidth,frame=on]}

也可以用 \METAPOST\ 代码将页码可视化，使之成为进度条，例如：

\starttyping[option=MP]
\startuseMPgraphic{processbar}
numeric w, n, s, t; path p; picture q;
w := \overlaywidth; n := \lastuserpage;
s := .5w / (n + 2); t := \userpagenumber - 1;
p := (fullsquare scaled \overlayheight);
pickup pencircle scaled 2pt;
q := image(for i = 0 upto n - 1:
             p := (p shifted (2s, 0)) randomized .5pt;
             if t = i: fill p withcolor darkgreen; fi;
             draw p withcolor transparent(1, 0.5, darkgray);
           endfor;);
draw q xsized w;
\stopuseMPgraphic
\stoptyping

\starttyping[option=TEX]
\defineoverlay[process][\useMPgraphic{processbar}]
\setupfootertexts[{\framed[frame=off,offset=0pt,
                           width=\textwidth,height=.8em,
                           background=process,empty=yes]{}}]
\stoptyping

\noindent 上述代码唯一需要解释之处是，当 \type{\setupfootertexts} 只有一个参数时，该参数的值会被安置在页脚的中间区域。上述代码构造的进度条效果如图 \in[processbar] 所示。

\placefigure[here][processbar]{第 2 页幻灯片}{\externalfigure[12/slides-finished.pdf][width=.6\textwidth,page=3,frame=on]}

\section{封面}

\index[standardmakeup]{\type{standardmakeup} 环境}
幻灯片的封面可使用 \type{sandardmakeup} 环境制作，见下例。

\index[standardmakeup]{standard makeup}
\starttyping[option=TEX]
\startstandardmakeup[align=center]
\ssd\color[darkred]{如何用 \CONTEXT\ 制作幻灯片}
\blank[2*line]
\ssb\darkred{李某人}
\blank[3*line]
\darkred{2025 年 09 月 01 日}
\stopstandardmakeup
\stoptyping

之所以用 \type{standardmakeup} 环境制作封面，是因为它能构造完全空白的单页，且该页不参与页码计数。
\placefigure[here][cover]{封面}{\externalfigure[12/slides.pdf][width=.6\textwidth,page=1,frame=on]}

若想让封面赏心悦目，最好的办法是制作一幅与幻灯片所讲主题相适且比例与幻灯片页面相同的图片，将其设为封面背景。假设背景图片为 foo.png，将其设定为封面背景的方法如下：

\starttyping[option=TEX]
\definelayer[cover][width=\paperwidth,height=\paperheight]
\setlayer[cover][preset=lefttop]
         {\externalfigure[foo.png][width=\paperwidth,height=\paperheight]}
\setupbackgrounds[page][background=cover]
\startstandardmakeup[align=center]
... 省略封面内容 ...
\stopstandardmakeup
\stoptyping
\placefigure[force][slide-background]{全页插图背景}{\externalfigure[12/slides-finished.pdf][width=.6\textwidth,page=1]}

你也可以尝试用 \METAPOST\ 语言画一些图形作为封面背景。这份文档的封面上像迷宫一样的线条便是用 \METAPOST\ 代码画出的。

至于幻灯片最后的致谢页，亦可视为封面，用 \type{makeup} 环境制作。

\subject{结语}

一份精致的幻灯片样式，值得你用心设计，但是切记，不要喧宾夺主。质胜文则野，文胜质则史。孔子说，好的幻灯片样式，应该是文质彬彬的。你可以将自己亲手制作的幻灯片样式保存下来，以后可重复使用，也可以分享给他人。不过，制作幻灯片只是帮助你学会页面布局的掌控方法，后者能够帮助你排版更多类型的文档。
