26 制作幻灯片

26.1 先容

R Markdown文件(.Rmd)文件支撑多种输出, 如网页(html_document)、MS Word(word_document)、PDF(pdf_document, 需要LaTeX编译器支撑)等, 还支撑生成网页格式的幻灯片(slidy_presentation, ioslides_presentation), 以及LaTeX beamer格式的PDF幻灯片(beamer_presentation), 和微软 Office的PowerPoint幻灯片格式。

26.2 Slidy幻灯片

Rmd文件选用输出格式slidy_presentation可以生成网页格式的幻灯片, 并具有缩放字体大小、显示幻灯片目录等功能。 只要在.Rmd文件开头的YAML元数据部分指定output: slidy_presentation。 因为幻灯片的单位是帧(frame), 与论文的结构有很大区别, 所以幻灯片Rmd文件很难同时作为论文的源文件。

26.2.1 文件格式

幻灯片分为多个帧,每帧用二级标题作为标志并以其为标题。 二级标题就是行首以两个井号和空格开始的行, 或者在标题下面画由减号组成的线的行。 用一级标题作为单独的分节帧, 将单独显示在一帧中。 一级标题是行首以一个井号和空格开始的行, 或者在标题下面画由等于号组成的线的行。

帧也可以没有标题,比如仅有照片的帧, 这时, 用三个或三个以上的减号连在一起标识新帧的开始。

一个简单的slidy_presentation幻灯片源文件example-slidy.Rmd, 内容如:

26.2.2 幻灯片编译

幻灯片用RStudio的knit按钮编译, 选择输出格式为slidy_presentation, 结果在浏览器中播放, 最好使用外部浏览器而不使用RStudio自带的浏览器, 自带的浏览器在显示数学公式时对网络环境条件有要求而且不能完美地支撑关于数学公式的本地设置。

除了使用knit按钮,还可以用类似如下命令:

其中mydemo.Rmd是源文件。

为了制作幻灯片,最好单独设置一个RStudio项目, 并且此项目仅生成幻灯片, 而不生成普通网页、Word、PDF等输出, 否则可能造成结果混乱。 希翼rmarkdown包的后续版本能取消这个限制。

26.2.3 播放控制

播放时,用如下方式控制:

  • 鼠标左键单击、光标右移键、向下翻页键、空格键都可以翻到下一页;
  • 光标左移键、向上翻页键回退一页;
  • 单击下方的Contents或单击C键显示幻灯片目录列表,可单击转移到任意页面;
  • Home键回到幻灯片开头;
  • 用A键切换是否将所有页面合并显示成一个长的网页;
  • 用S键缩写字体,用B键放大字体;
  • 通过选择保存为PDF的打印机进行打印, 可以将幻灯片转换为PDF, 但是打印生成的PDF仍是每页仅有原来的一帧, 所以转换成一个单页的HTML再打印可能更合适。

26.2.4 生成单页HTML

对slidy幻灯片的Rmd源文件不加修改, 也可以通过命令直接转换为普通的单页HTML文件, 但是因为在slidy幻灯片源文件中二级标题用来分帧, 而普通Rmd文件中二级标题用来分小节, 所以生成的单页HTML文件会有许多小节。 这样的文件更适合打印以及转换为PDF文件。

命令如:

26.2.5 数学公式处理与输出设置文件

讲课用的幻灯片经常会有数学公式, 比较关键的问题是数学公式如何处理。 网页中的数学公式一般使用一个公开的自由Javascript库MathJax显示, 但是这个库很大, 如果使用远程的库, 在网络不畅通时显示公式就不正常。 更好的办法是使用局部的MathJax库或将MathJax库安装在临近的网站服务器上。

为了使用局部的MathJax库, 简单的办法是在YAML的ioslides_presentation项目下面指定mathjax: local, 如:

上述办法容易使用, 缺点是多个不同的演示项目无法共用一个局部的MathJax库, 生成的结果包含了许多小的支撑文件。

为此, 可以将MathJax库装在演示项目所在目录的上层(比如上两层的MathJax目录内), 将设置MathJax的代码放在_header.html文件中, _header.html中的内容如:

在演示项目所在目录中增加一个_output.yml文件, 这使得该项目所有输出的共用的输出设置,内容如:

这里关闭了self_contained选项, 设置了MathJax库在本地目录,具体是演示项目所在目录上面两层的MathJax目录中。

公式中如果有中文, 开始时可能显示不正常, 这时右键点击公式弹出菜单选择“Math Settings–Math Renderer”, 取为“HTML-CSS”或“SVG”应可解决问题。

上面的输出设置文件中也设置了输出html_document, 这是单页的HTML格式, 取消了自动章节编号, 因为源文件中每帧都是一个小节。

26.2.6 其它选项

slidy_presentationfont_adjustment: -1可以缩小字体一号, 类似可以设为+1-2等。 在播放时也可以用S和B键缩小或放大显示。

可以在播放时在浏览器状态栏显示倒数计时器, 用slidy_presentationduration: 5表示每帧显示5分钟。 这是总的预计时间, 适用于演讲有时间限制的情况。

可以用footer属性指定每帧都显示的状态栏脚注,如:

slidy_presentation输出属性incremental: true可以使得列表显示需要每点击一次才显示下一项。

26.2.7 slidy幻灯片激光笔失效问题的修改

slidy幻灯片翻页是用空格、左右光标、上下翻页键, 而一般激光笔翻页是模拟上下光标键。 为此, 在安装的RApp目录的 library/rmarkdown/rmd/slidy/Slidy2/scripts子目录中, 找到slidy.js文件, 用编辑器打开, 用编辑器的搜索功能搜索key == 37, 将其替换成key == 37 || key == 38, 这里37是向左光标的编码, 替换后就是向左或者向上光标。 用编辑器的搜索功能搜索key == 39, 将其替换成key == 39 || key == 40, 这里39是向右光标的编码, 替换后就是向右或者向上光标。 修改完毕后保存, 然后将slidy.js用文件压缩程序(如7zip)压缩为slidy.js.gz。 这样就可以在用rmarkdown制作的slidy_presentation结果中支撑激光笔翻页了。

这样修改后, 如果某帧超高, 需要滚动显示, 就只能通过鼠标滚轮滚动了。

26.3 MS PowerPoint幻灯片

powerpoint_presentation输出格式可以生成MS PowerPoint文件。 设置如:

可以用powerpoint_presentationreference_doc属性指向一个.pptx的文件, 作为模板, 模板中的样式将被输出结果采用。

可以用Rstudio的Knit快捷图标实现转换(选其中的knit to PowerPoint), 或者用如下命令:

如果从bookdown内容转化成演示幻灯片, 需要大量修改原始文件内容, 设置成幻灯片常用的逐条播放格式。 如果不希翼进行这样的修改, 可以直接在MS PowerPointApp中直接输入或者复制粘贴已经编译好的网页格式输出的内容。 这样复制粘贴有一个缺点, 就是基于MathJax显示在网页中的公式, 无法通过复制粘贴转换到PowerPoint中。 一种办法是用rmarkdown将需要转换的带有公式的Rmd文件编译为Word格式或者PowerPoint格式, 再复制进入PowerPointApp的新页面中。 编译为Word格式的命令如:

26.4 Bearmer幻灯片格式

上述Slidy格式的幻灯片, 也可以通过LaTeX编译器转换成LaTeX beamer格式的幻灯片, 设置如:

其中slide_level用来规定几级标题开始新的一帧。 theme指定一种主题, colortheme指定一种配色方案, in_header在LaTeX导言部分插入preamble.tex, 内容见23.12

编译命令如:

结果是一个PDF文件。

截止到2019年7月时,编译不成功。 原因在于Rmd到Beamer幻灯片的转换是预期使用pdflatex引擎的, 而中文更适合用xelatex引擎, 但目前的rmarkdown包中beamer幻灯片功能对xelatex引擎支撑不足。

如果是纯英文内容的幻灯片, 可以在上面的设置中去掉关于latex_engine的设置并在preamble.tex中去掉与中文有关的内容,则可以编译成功。

26.5 R Presentation格式

R StudioApp单独提供了对一种R Presentation格式的源文件的支撑, 以.Rpres扩展名结尾, 是一种特殊的R Markdown文件, 与slidy的源文件也类似。

Rpres文件编译为HTML格式的幻灯片, 使用reveal.js控制显示。 reveal.js中也有对激光笔支撑不好的问题, 这是因为reveal.js中用向右光标键翻页, 对向下光标另有定义, 激光笔一般是模拟向下和向上光标键来翻页的。 为了支撑激光笔, 找到RStudio的安装目录, 在resources/presentation/revealjs/js中找到reveal.js文件, 在文件编辑器中打开, 通过搜索找到case 38:, 将其剪切到case 33:后面, 变成case 33: case 38:。 找到case 40:, 将其剪切到case 34:后面, 变成case 34: case 40:。 同一目录还有一个reveal.min.js文件, 也进行上述修改。