[Emacs] Org-Beamer 导出 slidshow (PDF)

简介

在之前公司转正答辩做 PPT 的时候就已经萌生了这种想法了:通过写代码来做 PPT 。这种想法起源很简单, Latex 就是一个典型的例子嘛,丢弃鼠标,完全通过代码控制排版。当时想的是这种东西应该有很多成熟的项目,而后来没怎么做 PPT 也就忘了。直到前段时间刷到一个视频,它介绍了如何通过 Markdown 来做 PPT, 于是死灰复燃,开始折腾起来。跟 Org Mode 相关的项目也有,我试了几个:

reveal.js vs spectacle.js

reveal.js 把每个 frame 放到 section 下,具体可以去看官网。 spectacle.js 就类似传统的幻灯片。

这两个 HTML 的演示都非常好看,动画丝滑流畅,且可以做到 all-in-one, 就是把所有 js, css 压缩到一个 HTML, 方便携带。

我只是想做一些简单的幻灯片,想着不整这么复杂,这些主题啊什么的要用 js/css 去调,我不太会,最终转向 org-beamer.

Beamer

Beamer 属于 Latex 的一个库,通过 latex 文档生成幻灯片。我想的是它是 org mode 内置的,使用起来应该比较简单,事实上也很简单 -–— 如果你使用别人的样式的话。

安装

org-beamer 是 Org Mode 自带的,因此只需要安装 Beamer 相关的环境就行了。

我使用的是 Tex Live ,安装 Arch Linux 官网上,把能安装的都安装了:

sudo pacman -S texlive-most texlive-lang texlive-fontsextra

Emacs 配置

Emacs 这边不需要太多配置,主要是解决中文相关的问题 [1]

(with-eval-after 'ox-latex
  ;; 使用xelatex一步生成PDF
  (setq org-latex-pdf-process
        '("xelatex -interaction nonstopmode -output-directory %o %f"
          "xelatex -interaction nonstopmode -output-directory %o %f"
          "xelatex -interaction nonstopmode -output-directory %o %f"))

  ;; 设置默认后端为 `xelatex'
  (setq org-latex-compiler "xelatex")

  ;; 在 Latex 文档导言区添加 \userpackage{xeCJK}
  (add-to-list 'org-latex-packages-alist '("" "xeCJK"))

  ;; 幻灯片标题
  (setq org-beamer-frame-level 2)
  )

基本概念

在 Beamer 中,架构如下所示:

  • 绿色、紫色(大概是,我也不知道我调的啥色)代表了两个 Sections, 即章节,每个章节包含了多张幻灯片
  • 每一张切片是一个 Frame, 也就是一张幻灯片
  • 蓝色和红色代表 Blocks, 即块,就是幻灯片里面的小窗口

org-beamer 使用

官方文档:《The Org Manual

编辑增强

.org 里面加上头: #+startup: beamer, 可以提供额外的编辑帮助,比如补全标签、补全属性等。

org-beamer-frame-level

首先要关注的是一个变量: org-beamer-frame-level, 在配置那里给它设成了 2 ,它的含义是:

  • 所有等级小于它的标题,会被视为 Section
  • 所有等级等于它的标题,会被视为 Frame
  • 所有等级大于它的标题,会被视为 Block

来看一段框架:

* 第一章 
** (第一张幻灯片)
第一张幻灯片的内容

** (第二张幻灯片)
第二张幻灯片的内容

* 第二章
** 块的展示
这里展示两个块元素

*** 第一块
这里是第一块

*** 第二块
这里是第二块

使用 C-c C-e l P 来在同一目录生成同名的 PDF 文件。输出如下:

bb4329ae061bdc2be8a07c77da6e5398.png

Figure 1: 目录

4e7d7db91a0253da4f8719abd913695c.png

Figure 2: 内容

对于不同的文件,可以通过 options 来设置:

#+options: H:1

头信息

文件设置头消息,然后 org-beamer 会根据模板为我们生成封面、页眉、页脚、侧边栏等。

#+title: 示例幻灯片
#+subtitle: 子标题,如果没有就不显示
#+date: 2022-01-01,如果没有就默认是今天

# 显示作者
#+options: author: t
#+author: Finger Knight

# 使用主题, Madrid 是 Beamer 内置的
#+BEAMER_THEME: Madrid

输出封面:

富文本

强调倾斜 等富文本正常使用。

Block 块

根据前面的配置, 3 级标题及以上会被视作块,也就是每张 Frame 里面的小框框。

类型

在 Beamer 中有三种不同类型的 Block: 普通、警告和示例。通过设置标题的属性 BEAMER_ENV 来实现,三者分别对应的是 block, alertblock, example.

** 块类型
*** 普通块
:PROPERTIES:
:BEAMER_ENV: block
:END:
这里是普通块。

*** 警告块
:PROPERTIES:
:BEAMER_ENV: alertblock
:END:
这里是警告块。

*** 示例块
:PROPERTIES:
:BEAMER_ENV: example
:END:
这里是示例块。

没有设置 BEAMER_ENV 的块默认为普通快(block)

此外,还有一种类型 ignoreheading, 即忽视标题,这个块会像一个段落一样,不会有框框作用在上边。但如果想要标题背景,不想要文字,标题留空不行,要用到 @@beamer: ~~@@, 见后面的例子 [2]

宽度

通过标题属性 BEAMER_COL 来设置列宽。它是一个 [0,1] 区间上的一个小数,表示当前块宽度占整个 Frame 宽度的比例。如果相邻两个快的宽度之和小于 1 ,就可以实现两个并排的块。

如果同一 Frame 下的连续块太多,宽度和超过 1 org-beamer 不会自动换行,然后所有块都挤到一行。目前我找到的办法是在该分行的地方创建一个空块:

***
:PROPERTIES:
:BEAMER_ENV: ignoreheading
:END:

因为空文本,所以它不会占据空间。

单行 columns

有一个 BEAMER_ENV 的值 columns, 它用于把它下面的标题变成块,使得它们都限定在当前行内。因此它可以做到无视块之间的间距,尽管它们可能会重合 [2]

** Frame
*** 第一行
:PROPERTIES:
:BEAMER_env: columns
:END:
**** 左边
:PROPERTIES:
:BEAMER_env: block
:BEAMER_col: 0.5
:END:

**** 右边
:PROPERTIES:
:BEAMER_env: block
:BEAMER_col: 0.50
:END:   

*** 第二行
:PROPERTIES:
:BEAMER_env: columns
:END:
**** @@beamer: ~@@
:PROPERTIES:
:BEAMER_env: block
:BEAMER_col: 0.99
:END:
即使左边 0.99 也能排下

**** @@beamer: ~@@
:PROPERTIES:
:BEAMER_env: block
:BEAMER_col: 0.01
:END:

动画

“动画”是给伪概念, PDF 哪来的动画一说,只能说是简单的通过重叠重复的方式来实现块元素的出现和消失。

\pause

\pause 就像断点一样,在当前处放了之后,演示到这里时会“停下”,即后续内容先不展示,下一页开始出现。

在 Org Mode 中的使用是: #+BEAMER: \pause

块的动画

通过设置 BEAMER_ACT 属性来控制动画,其值用一对尖括号 <N> 包裹,其中 N 表示出现的位置。

单个数字,表示第几个位置出现。如 <1> 表示在一开始就出现, <2> 表示在第二个位置出现,即下一页。以此类推。这个数字并不会真正改变当前的“页数” -–— 见下图,右下角,还是在同一 Frame 下 -–— 所以我更愿意称它做“位置”。

** 动画
*** A
:PROPERTIES:
:BEAMER_ENV: block
:BEAMER_ACT: <1>
:END:

*** B
:PROPERTIES:
:BEAMER_ENV: block
:BEAMER_ACT: <2>
:END:

*** C
:PROPERTIES:
:BEAMER_ACT: <3>
:BEAMER_ENV: block
:END:

输出会得到三张幻灯片:

横杠 (-) 表示连续范围,如: <1-2> 表示出现在 1 和 2 位置。如果横杠后的数字没制定如 <2-> ,就表示出现到当前 Frame 结束.

** 动画
*** A
:PROPERTIES:
:BEAMER_ENV: block
:BEAMER_ACT: <1->
:END:
一直出现

*** B
:PROPERTIES:
:BEAMER_ENV: block
:BEAMER_ACT: <2>
:END:
位置 2 出现,其他位置不出现

*** C
:PROPERTIES:
:BEAMER_ACT: <2-3>
:BEAMER_ENV: block
:END:
地址 2 到地址 3 出现,其他位置不出现

*** D
:PROPERTIES:
:BEAMER_ACT: <4>
:BEAMER_ENV: block
:END:
地址 4 才出现

4e83670e09f0b085287bd6405eaf91b9.png

Figure 3: 输入法问题,“位置”打成“地址”,但不想改了

逗号 (,) 表示“与”,可以用来指定离散开的页数,如 <1,3,6> 表示出现在位置 1, 3 和 6 。也可以和范围组合,如 1,4,7-10 表示出现在位置 1, 4, 7, 8, 9.

文本强调

给一段文本加上强调,在到达位置时会变色。先用 * 把文本包裹,然后在文本前加上命令: *@@beamer:<N>@@要强调的文本*

** 文本强调
这是一段文本,最后两个字是强调 *@@beamer:<2>@@文本* 。因为是 2 所以是下一页强调,如果是 1 就是当前页。

列表

在列表前添加属性 #+attr_beamer: :overlay <+-> ,接下来列表的各项会依次出现,且出现过的一次出现。对于某一项,可以在其对应行开头使用 @@beamer:<N>@@ 单独设置。

** 列表
#+attr_beamer: :overlay <+->
- Item1
- Item2
- Item3
- @@beamer:<3>@@ Item4
- Item5

图片

直接通过 Org Mode 的链接插入即可,通过 #+attr_latex: 来设置属性,比如常用的宽度 :width .6\textwidth , 或者是缩放 :scale 0.5 ,标题 :caption Title 等等

重复页面

重复页面简单说就是复制之前的某个页面,比如讲到后面的内容,需要回顾前面的某些页面 [3]

** Again
:PROPERTIES:
:BEAMER_ENV: againframe
:BEAMER_ACT: 2-
:BEAMER_ref: id:a047ce4d-288b-4137-853a-d4e757d293c4
:END:
  • BEAMER_ENV 设为 againframe, 标题不用,因为重复了目标页面的标题
  • BEAMER_ACT 表示显示范围,和动画的格式一致,只是不用加尖括号
  • BEAMER_ref 要重复的页面,可以用 *标题 来跳转,但为了防止某些重名标题,最好使用 ID. 目标页面通过 M-x org-id-get-create 来添加一个随机 ID, 然后使用 id:xxx 链接过去。

其他 Latex 命令

想使用额外的 Latex 命令,用 @@beamer:code@@ 来执行。

目录

开启目录: #+options: toc: t, 便会在封面首页之后插入一页目录页。

设置 #+TOC: headlines [currentsection], 则会在进入每一个章节的时候插入目录页,同时高亮即将要进入的章节。

#+options: toc: nil, 关闭目录。

具体目录层次及其他更多相关设置参考文档:《The Org Manual》。

自定义样式

这里给一个博主的博文,有很大帮助:《Latex - 随笔分类 - 南宫二狗 - 博客园》,找到 Beamer 相关文章即可。

结构

Beamer 将样式分为 4 块:

  • 主题,包含了方方面面的样式,一般以下三个会包含其中。通过 #+BEAMER_THEME: 来调用
  • 颜色主题,就是规定了各个模块,如文字、 Frame 标题等的颜色。通过 #+BEAMER_COLOR_THEME: 来调用
  • 字体主题,规定了各个模块使用的字体。通过 #+BEAMER_FONT_THEME: 来调用
  • 内部主题,规定了比如 Block, 列表的样式,像是无须列表前是原点还是小方块。通过 #+BEAMER_INNER_THEME: 来调用
  • 外部主题,规定了各组分之间如页眉页脚、侧边栏等的样式。通过 #+BEAMER_OUTER_THEME: 来调用

事实上,也可以通过一个文件就全部包含了,这样模块化的好处就是可以弄出各种各样的组合,满足不同场景,更加灵活。

这里给内置的样式 [4] ,没用完,我基于其中的主题自己写了一套。

  • theme: Madrid, sidebar, Bergen …
  • colortheme: dolphin, dove, seagull …
  • fonttheme: default, professionalfonts, serif, structurebold, structureitalicserif, structuresmallcapsserif
  • innertheme: default, circles, rectangles, rounded, inmargin
  • outertheme: default, infolines, miniframes, smoothbars, sidebar, split, shadow, tree, smoothtree

想要自定义颜色,需要基于内置的主题做参考去配置,其路径在 tex/latex/beamer, 在 Arch Linux 下绝对路径: /usr/share/texmf-dist/tex/latex/beamer.

其命名方式是: beamer<type><name>.sty, 其中 <type> 是主题类型, <name> 是主题名字。比如要写一个名字为 mylight颜色主题就是 beamercolorthememylight.sty, 把它放到环境变量的路径下就能够识别了。

在主题( theme )中,通过 \usecolortheme{}, \usefonttheme{}, \useinnertheme, \useoutertheme 来导入相关的样式。

我的主题在 fingerknight/presentation ,自己也是摸爬打滚、复制粘贴过来的,我没有总结出系统性的内容,但目前满足我的需求。更多资料可以看参考资料:

Powered by Org Mode.