第 5 章 话说Xaringan
5.1 Xaringan缘起:创建课程slide
5.1.1 从前有座山
现在对(本科)教学工作的要求,已经发生了很大的改变:教学的内容变得更加专业化和细分化(学生就业市场的倒逼);教学过程/流程需要标准化(一切变得透明公开);教学活动应该能够便于复制并规模化运行(课程最好能以公开课/慕课方式运作);个性化教学和灵活性调整被反复强调(对学生多元考核、“一人一套试卷”);其他方面。
教师在讲台上的台前“艺术化”魅力(仪态、表情、音色等)已经不再如曾经那么重要;教师在台后的“技术性”设计(内容、互动、展示等)上升到了无与伦比的地位。
尤其是对于哪些技术性课程,如计量经济学(Econometrics)和统计学(Statistics),“技术性”设计必须要赶上这些教学新要求的呼声。(当你发现一位大学教师还在“坚持”使用Office2007,你一点都不要惊讶——经管现在已经是2019年了。)
5.1.2 逃离PowerPoint,拥抱HTML5?
为什么要逃离PowerPoint,拥抱HTML形式的slide?下面分别来说一说。
5.1.2.1 PowerPoint的“断、舍、离”
office版本太过分散,ppt可能会上演各种“变形记”。(现在国内有很多学生,已经不能区分WPS和Office了。学生的毕业论文或作业提交,那酸爽,真是谁看谁知道。)
ppt维护和更新的各种“梗”。最让我纠结的就是mathtype公式,神一般地会一夜之间“变砖”(倒腾几下,公式变图片,或者干脆显示不了),更不要说公式的重复使用和编辑修改。如果使用一些新技巧、新字体,那一定会让你记住“凡走过的都是一个一个的巨坑”。
难以逾越数据、图形和模型分析的“天堑”。表格数据加总等分析基本等于不可能(事实上也可以关联excel,但是“关联越多,等价于羁绊越多”!);数据图形化,你只能老老实实拷贝统计软件里的做好的图吧(泪奔!);建模分析结果的调用,就更别提了(反复在多个软件窗口中切换和敲键盘,眼花缭乱的“骚操作”不说,最担心的还是手一抖怕敲错了结果啊!)。
5.1.2.2 HTML形式slide的“前世今生”
一个浏览器就够了。HTML是互联网世界最广泛使用的交流形式。每台电脑都会安装浏览器(chrome、firefox、IE…),但不是都会安装Microsoft office全家桶(365家庭版那可是每年500RMB啊,心疼一下下!)。
一份文本多种输出形态的终极需求。就像KTV里嗨唱切歌,老师们常常要在word、pdf、html、ppt、png等格式中不断切换啊。一个逗号或减号,在word里改了,那还得改ppt啊,就问你蛋疼不蛋疼。所以,仅维护一份文本,随时获得各种输出(html、word、ppt、slide…)简直就是人类共同的梦想啊。
“纯文本”就是你的最底层“话语”。一切的文字、代码、图形、格式、排版…,统统汇集于一份“纯文本”中!Plain Text,正如其名,平铺直叙,朴素而不简单,包含了你所需的一切,你想说和想呈现的一切。
5.1.3 优势和不足
5.1.3.1 优势
R语言和RMarkdown的应用就是它最大的优势。这赋予了教学准备工作更强的“生产力”:代码可重复利用、统计处理和分析报告完美整合。
Xaringan Slide可以高度灵活的定制化。本质上形式的呈现,完全依赖于CSS技术,这与PowerPoint中的模板使用是完全不同的体验,效率上完全秒掉后者。
Xaringan Slide可以完美转成pdf格式的slide。其实直接用Chrome浏览器打开HTML Slide不就完了嘛,这种格式转换的操作本来就是多此一举!总之,你说,世界需要pdf;于是Xaringan便说,给你pdf!
与GitHub版本控制技术融合。我想说的是,这是一种全新的师生交互和反馈机制!
5.1.3.2 不足
对行内公式支持不是很友好。比如\(\beta\)的实现代码
$\beta$
必须要保持独立一行!一段话要是有很多这样的inline equation,那么xaringan::moon_reader文档就显得很破碎了。风格调整CSS技术的学习还是有一定成本的。换言之,制作一份自己喜欢的“专属”模板,还需要花费一些时间。
强迫症的一些小细节。使用
knitr::kable()
制表,转pdf时表格无法显示,替代办法就是用DT::datatable()
的表格风格,而它往往不是真正的Table风格!另外,就是windows环境下,不支持Rstudio面板Viewer中预览slide,只能在浏览器中预览。
5.2 Xaringan发布:blogdown网站中的展示
本节介绍如何把Xaringan 演示Slides以静态网页(static webpage)形式载入个人网站。
主要参考资料和实现办法可参看:
Yihui Xie的blogdown中2.7 Static files
以上都有比较系统的说明,可以直接参照。
需求和问题列表:
静态网页方式损失了效率。
静态网页,正如其名,只能相对“固定”地加载封装好的.html文件或.pdf文件之类。显然,交互性和动态性就暂时难以获得。因为我们写作Slide是在另一个repo文件夹下(repo如course-econometrics文件夹下,并使用Xaringan包),然后确认没问题后才能把渲染好的.html形式的Slide文件(一般是如02-simple-reg-basic-slide.html)拷贝到网站repo文件夹指定目录下(repo如netlify,特定目录为\netlify\static\slides-course
)。同时,如果html文件不是完全自容的(self-container),那你还必须把使用到的图片数据等文件夹也一同拷贝过去(这就非常糟糕了!因为你的slide制作可能会经常变动或更新)。那么要如何自动关联Xaringan(实现slide)和blogdown(实现website)呢?
当然动态性和关联性也是有成本的。如果Xaring里的文件需要渲染很久(比如ggplot作图很多,数据分析很多),那么blogsite会负担比较大。
知识版权的保护问题。slide上传到website后,文字和图片等都可以任意拷贝下载。对于开源项目,这完全没毛病。但是,对于一些重视原创知识保护的人,这就是很大的“命门”了。
5.3 Xaringan效率:底层与简洁
一般而言,保持project下的文件夹结构稳定和简洁,能够大大避免工作的低效率性。Xaringan包用于制作多个系列slide幻灯片,也会难免带来文件数量和类型的逐渐增加和膨胀。那么在Xaringan框架下,如何管理和组织文件夹结构,以提升工作效率和代码稳定性?
5.3.1 底层逻辑
5.3.1.1 渲染方式
Xaringan slide的渲染方式主要有两类
静态渲染方式:Rstudio菜单knit
实时渲染有两种方式(live preview)
- Rstudio里插件 “Infinite Moon Reader”
- console里调用xaringan::xaringan::inf_mr()
5.3.1.2 共用文件夹的情形
mycss:假定课程里全部slide都使用同样的css风格。
pic:假定课程slide里的本地图片都放在pic文件夹下。
若干可能的文件体系结构及面临的主要问题
体系1“全部一起堆放”:随着Rmd文件数的增加,一级目录下会有很多文件!
chn-chpt01.Rmd; chn-chpt02.Rmd;……;eng-chpt01.Rmd; eng-chpt02.Rmd;……
体系2“分模块堆放”:比较合理。但是在实时渲染时,将面临如何管理css和pic等问题。子文件夹1:
Slide-chn:chn-chpt01.Rmd; chn-chpt02.Rmd;……
;子文件夹2:Slide-eng:eng-chpt01.Rmd; eng-chpt02.Rmd;……
5.3.2 效率方法
5.3.2.1 减少系统复杂性
Yongfu的博客文章Tips to Reduce the Complexity of Slide Making with Xaringan,比较详细地介绍了如何减少xaringan制作复杂性的一些方法。
- 使用子文档(child document)架构(see rmarkdown cookbook: 16.4 Child documents)。
5.3.2.2 提高代码复用性
引用代码块。前后slide如果要多次(2次及以上)用到同样的代码块,则可以使用代码块标签索引(see rmarkdown cookbook: reference labels)。具体有两种操作情形:
- 简单重复引用代码块。先定义label,然后直接使用相同标签的代码块头即可。
- 组合引用多个代码块。先定义label,然后设定
ref.label=
参数进行引用即可。
# 简单重复引用代码块
`` `{r, chunk-one, eval=TRUE} # def
some long content balabala
`` `{r, chunk-one, eval=TRUE} # use
# 组合引用多个代码块
`` `{r chunk-a} # def1
some long content balabala
`` `{r chunk-b} # def2
some long content balabala
`` `{r chunk-a, ref.label=c('chunk-c', 'chunk-b')} # use
5.3.2.3 修改预览实时化
- 赶紧去看Yihui的blog,The Ultimate Infinite Moon Reader for xaringan Slides。赶快安装更新包:
remotes::install_github('yihui/xaringan', upgrade = TRUE)
- 而且是Windows用户的又一个福音啊。前面刚说Rstudio里不能Viewer预览,但是更新Xaringan包后发现Chrome浏览器竟然可以“实时”同步预览了!yoo!
定制自己的字体大小:
- 在Rmd文档里添加代码:(参看Customize font size for all the slides in xaringan)
<style type="text/css">
.remark-slide-content {
font-size: 30px;
padding: 1em 4em 1em 4em;
}
</style>
5.3.2.4 选用一个好模板
比如我使用的杜克大学模板:Slide Template for Duke University。
初学者最好先不要删除模板的内容,里面的示例说明可以很好地参考。
5.3.2.5 定制个性化模板
关于动画设置。并不是ppt的专利。可以实现的,请参看Animate Xaringan Slide Transitions。
关于定制样式。世界另一头,总有一个大牛,已经做好了包供你使用,具体请看xaringanthemer。
5.3.2.6 小结
xaringan实时渲染方式,会调用servr package来搭建本地网页服务参看官方文档
因此实时渲染下:本地服务会寻找一个根目录(root directory),从而会引发上述的图片渲染问题。libs文件夹总是会和.Rmd文件并列
总之,使用相对路径引用图片是比较保险的方式。具体的地方包括
remark.js背景图:
background-image: url("../pic/a.png")
R函数正文图:
include_graphics("../pic/a.png")
markdown行内图:
![]("../pic/a.png")
其次,css的yaml设置
css:
- default
- default-fonts
- duke-blue
- hygge-duke
- ../mycss/my-custom.css
5.4 Xaringan美化:CSS功夫
本节内容总结了CSS的学习架构和逻辑体系,并专门针对Xaringan slide制作技术进行了探索和应用。
5.4.1 再谈Xaringan的本质
Xaringan背后是基于remark.js的。remark.js后台基本工作流程,就是采用JavaScript语言把markdown文档,映射到html上,并形成独特的slide幻灯片样式。因此,还是很有必要了解一下remark.js的说明文档(见Wiki页面)。那么Xaringan包又起到了什么作用呢?根据yihui的说法:它扩展支持了Rmarkdown语法以及R代码的直接运行!
Xaringan本质上是以html形态呈现,并使用css样式进行style视觉美化。Xaringan的技术讨论和细节见其wiki页面。
归结起来这是对slide工具的一种选择,而且是选择了”未来感”的html呈现形态!那么CSS知识这是绕不过去的学习壁垒。html和css的学习至少也是需要在”三姑学院”(W3school)的汪洋里过水”捞一遍”(通读一遍)。
5.4.2 头衬和底衬(header and footer)
调整header和footer视觉效果,主要是从某个slide开始里设定layout: true
,并按html语法设置header和footer样式。其完整的语法如下:
<!---slide area with layout--->
---
layout: true
<div class="my-header-h2"></div>
<div class="watermark1"></div>
<div class="watermark2"></div>
<div class="watermark3"></div>
<div class="my-footer"><span>huhuaping@    <a href="#chapter01"> 第01章 导论</a>
             
             
<a href="#sec-process">1.3 计量经济学分析过程</a> </span></div>
---
具体样式细节包括:
- heading文本居中设定。需要注意叠放层级参数
z-index
的设置。
.remark-slide-content h2, h3,h4,h5{
position: relative;
top: 0px;
margin: 15px 0px 50px;
width: 99%;
text-shadow: 0px 0px;
text-align: center;
z-index: 5;
}
- header背景色和渐变方式。
div.my-header-h2 {
background-color: #FFFFFF;
background: -webkit-gradient(linear, left top, right top, color-stop(0%,#f77a00), color-stop(0%,#f77a00), color-stop(10%,red), color-stop(74%,#fbd0ac), color-stop(83%,#fbd0ac), color-stop(100%,#fddfc8));
position: fixed;
top: 0px;
left: 0px;
height: 86.92913px;
width: 100%;
}
- footer导航样式。
div.my-footer {
background-color: #272822;
position: absolute;
bottom: 0px;
left: 0px;
height: 20px;
width: 100%;
}
div.my-footer span {
font-size: 10pt;
color: #F7F8FA;
position: absolute;
left: 15px;
bottom: 2px;
}
- footer的导航链接功能。先在css里设定链接文本的颜色,然后在slide里设定
layout: true
(见前面完整语句块),并按html语法设定链接定位#a-specify-id
。
5.4.3 添加水印图片(watermark)
水印图片的个性化设定。首先需要设定css,然后在slide里设定layout: true
(见前面完整语句块),并按html语法依次设定三个水印图片,其中之一如<div class="watermark1"></div>
。
/* water remark image */
.watermark1::after {
content: "";
display: block;
width: 30%;
height: 20%;
position: absolute;
top: 150px;
left: 100px;
background-image: url("vlog-nwsuaf.jpg");
background-size: 80%;
background-position: 0px 20px;
background-repeat: no-repeat;
opacity: 0.04;
/* Rotate div */
-ms-transform: rotate(-45deg); /* IE 9 */
-moz-transform: rotate(-45deg); /* firefox */
-webkit-transform: rotate(-45deg); /* Chrome, Safari, Opera */
transform: rotate(-45deg);
}
为了保证水印图片(<div class='watermark'>
)总是显示在最下层,则需要使用css样式z-index: 1
来调节页面各个元素(<p>
或<ul>
等)的层次关系。需要注意的是css样式z-index:
要发挥作用,则要求这些元素的共同parent node(<div class = 'remark-slide-content'>
)必须满足css样式position: relative
。相关资料可以参看队长问答(Position one element relative to another in CSS)。
5.4.4 添加logo图片
方案1:手工添加logo。可以参看:a. xaringan Tip: Add A Logo to All of Your Slides。以及“队长论坛”贴文“Can I add a logo to every slide of a xaringan template using css?”。
方案2:包函数添加logo。xaringanExtra::use_logo(
能很好地处理logo图片,可以灵活使用class:hide_logo
来指定特定slide不显示logo图片。具体请参看官方说明。
5.4.5 各类窗框(notes box)
在多个写作场景下(如xaringan
、blogdown
、rmarkdown
),可能会用到各类提示窗框(notes box)。可以利用css设定获得个性化的提示窗框效果,具体可参看desirée de leon的博文1。
基本要点:
背后要用到html的
div
语块可以借用R包
bookdown
的blocks
代码块,进行快捷应用。
第一步:css文件(/my-css/notes-tips.css
)设定如下:
/* -----------div tips------------- */
div.puzzle, div.fyi, div.demo, div.notes {
padding: 0.5em;
margin: 0.5em 0;
padding-left: 100px;
background-size: 70px;
background-repeat: no-repeat;
background-position: 15px center;
min-height: 100px;
color: #1f5386;
background-color: #bed3ec;
border: solid 5px #dfedff;
}
div.notes {
background-image: url("notes-light-bulb-ff5500.png");
}
注意:需要自己手动下载背景图片,免费的图片icon下载网站有:
- iconfinder。需要账号登陆。
- fontawesome.com。图标可以先编辑,在下载。正文里还可使用R函数
fontawesome::fa('slideshare')
。例如slide图标- aiconica.net。搜索功能比较弱。
第二步:在.Rmd
文件的yaml
区域引用上面的css文件路径。
css:
- ../mycss/notes-tips.css
第三步:在.Rmd
文件下进行写作,并引用对应的css样式:
` ``{block, type='notes', echo=T}
待完成:找到新数据,绘制一张条形图,但其不适合制作柱状图。
` ``
Xaringan slide下对div css的调用(以div.notes为例):
.notes[
here is your point.
]
bookdown或大部分html输出的Rmd下对div css的调用(以div.notes为例):
:::notes
here is your point.
:::
5.4.6 序贯图片的动画效果
幻灯片动画效果(animation)的背后,基本有两类思路:
第一类:小部件(partial elements)动画效果。常见的设计工具如pptx,在一张slide里面,对动画小部件(窗体、文本、箭头等)进行时序上(timeline)的安排设计,从而实现动画效果。比较适合于那些只需要利用“标准化”小部件组合形成动画的幻灯片。其优点也是显而易见的:一块幕布,持续添加小部件,比较符合动画的内容本质和视觉直觉。难点在于需要大量操作来给小部件定位(position)以及修饰小部件。
第二类,图片放映动画效果。利用人眼的视觉时间差特点,把事先设计好的系列序贯图片,连续反映展示,从而实现动画效果。比较适合于那些“手工绘制”多张序贯图片形成动画的幻灯片。其优点是:强调视觉定格(帧)关系,不太关注细节的严格一致。难点在于需要“手工绘制”,以及认为确定图片帧,小部件的细节可能会被认为并不太重要。
目前为止,直接在xaringan(或reveal.js)slide上进行第一类小部件动画制作的工具,基本上没有看到相关便利性的工具包或解决方案。xaringan(或reveal.js)slide上的动画主要是基于第二类,图片放映动画效果。例如,一个R相关会议报告做了题为Reproducible Data Workflows,就给出了“反映”型“流程图”(其实并不是流程)的动画效果,其背后就是利用序贯图片帧,不断反映,从而表现出“动画”效果。具体代码可参看其Rstudio cloud project。
总体而言,在xaringan(或reveal.js)slide上主要采用“放映”型动画效果,因为动画实现(多帧图片)和动画控制(方向键)都相对简单。然而,多帧图片的设计和获得则成了其中最大难题。这样就需要依赖R之外的“绘图”工具,而且它最好还要能够自动保存序贯图片帧(反映时序中的中间环节图片)。不过很遗憾,这样的外部“绘图”工具(不管是否支持小部件)目前我是暂时没有发现(起码放狗搜了一大圈是无所得)。
不过还是找到了一个可以实现的“笨办法”。
第一阶段:绘制图片阶段。用到的主要外部工具有Powerpoint
(用于绘图) 和Snagit
(用于截图)。工作流程基本上是:
利用
Powerpoint
绘图,设计好动画。在动画窗口中控制小部件的出现先后顺序。播放
Powerpoint
动画,再利用Snagit
进行截图,获得图片帧,按要求进行图片自动命名(这一步很重要,方便后面调用)。需要注意在Snagit
设置里,把截图质量设定为较高(File \(\Rrightarrow\) Capture perference \(\Rrightarrow\) Capture \(\Rrightarrow\) Videa Quality)
第二阶段:xaringan代码实现阶段。有了上述序贯图片,Xaringan里主要就是进行图片调用和css控制。
图片调用。因为涉及到调用系列图片(已经有规则地命名),因此可以将slide代码编程化,尽量减少代码数量,让文档结构更清晰。具体而言,需要用到的函数包括:
base::dir()
函数调用图片路径。glue:glue()
函数组装slide语法要素。base::cat()
函数输出代码结果。
CSS控制。图片相对位置等的控制,可以启用tachyons的CSS样式,具体要用到
xaringanExtra
包的xaringanExtra::use_tachyons()
函数。
注意:
-
glue::glue()
函数的使用有两个坑:一是它对方括号{your parameter}
敏感(默认为parameter),因此需要用双方括号嵌套,才能正确编写并识别latex代码\frac{{your code}}
;二是它需要双斜线\
来escape特定latex语法(如)。
-
R code chunk参数一定要记得设定
{r results=“asis”}
,这样才能实现正确代码输出(cat()
函数)。 -
Rmarkdown图片调用一般而言有两种途径,一是使用html标记语言
;二是使用
knitr::include_graphics()
。但是在序贯图片效果的图片调用中,目前只能使用第一种方法。因为knitr::include_graphics()
是一种顶级表达方式(top-level R expressions。具体 参看:yihui;以及贴文。)
下面是Xaringan中的代码演示:
# 启用tachyons的CSS样式
xaringanExtra::use_tachyons()
# 调用图片位置
proj_slides <-sort(dir("pic/sequence/", pattern = "quatile-min-upper-.+png$", full.names = T),decreasing = T)
# 组装slide代码要素
proj_slides_txt <- glue::glue("
## (演示)分位数计算:较小制上限插值公式(推导)
.fl.w-60[
![]({proj_slides})
]
.fl.w-40[
-
$f_i$表示各组所对应的频次,其中
$i \\in 1,2,\\cdots,5$。
$f_{{Q_j}}$表示分位数组的频次。
$p_j$表示1/4或3/4分割位置,其中:
$p_1=\\frac{{\\sum{{f_i}}}}{{4}}$,
$p_3=\\frac{{3\\sum{{f_i}}}}{{4}}$。
]
---
")
# 输出代码结果
cat(proj_slides_txt, sep = "")
下面的代码将对比说明图片调用的两种用法:方法1(可行)![]()
(序贯动画效果可
参看),以及方法2(不可行)knitr::include_graphics()
。
r ''````{r, results='asis'}
# 方法1(可行)`![]()`
cat(
paste0(
c("### 内生自变量情形1:遗漏变量(演示2)"),
"\n\n",
"具体地,遗漏变量引发内生自变量问题的直观演示如下:\n",
"\n",
paste0("![](pic/chpt11-endogeneity-ommit-seqence/chpt11-ommit-sequence-part-0",5:1,".png)"),
"\n\n",
"---\n\n",
sep = ""),
sep = "")
```
r ''````{r, results='asis'}
# 方法2(不可行)`knitr::include_graphics()`
cat(
paste0(
c("### 内生自变量情形1:遗漏变量(演示2)"),
"\n\n",
"具体地,遗漏变量引发内生自变量问题的直观演示如下:\n\n",
paste0("\`\`\`{r, fig.cap='animation-0",1:5,"'}"),
"\n",
paste0("knitr::include_graphics('pic/chpt11-endogeneity-ommit-seqence/chpt11-ommit-sequence-part-0",5:1,".png')"),
"\n",
c("\`\`\`"),
"\n\n",
"---",
"\n\n",
sep = ""),
sep = "")
```
5.4.7 灵活选用字体
解决字体灵活选用问题。工作量理论上不是很大,主要是受到中文字体适用性和加载速度等的限制。目前暂时还不想去碰它,大众字体就大众字体,先忍一忍。具体看yihui的相关思考和说明。如思源宋体 ;楷体。
在Xaringan中给slide内容设定不同的个性化字体,基本有两种方案(当然二者结合也是可行的):
方案1:个性化手动设置。首先,需要编写个性化字体CSS。然后,在
yaml区域
来指定调用字体CSS文件。Xaringan
包的官方wiki “Deploying Your Slides Online”给出了具体操作过程和办法。此外,还有一类是集成、友好性的css工具集,也可能更便捷地提供字体设定,例如Tachyons
的字体库管理方案。方案2:R包函数化设置。具体要用到R包
xaringanthemer
,其字体设置及相关R函数可参看其官方说明。
上述两种方案,其关键都在于可用“字体库”(font family)。因此需要弄明白如下几个问题:
Xaringan
默认的字体库是什么?它存放在哪里?(对于方案2的R包xaringanthemer
,我们也同样需要问这样的问题。)
Xaringan
字体css文件位置在:“your-pkg-dir-fonts.css”
操作系统(如Win 10 或Mac OS)的字体库(system font libraries)与
Xaringan
的字体库是什么关系?(后者能直接调用前者的字体库么?)电脑本地渲染的slide字体,与网站开发(如netlify)上的slide字体是什么关系?(后者可能需要设置netlify的后台相关字体控制参数)。
怎么来使用网络开源的字体库?slide的字体加载能否成功,以及加载速度够快么?
下面提供一些可用的免费字体库:
google font。找到自己喜欢的字体类型,例如Ma Shan Zheng,然后右侧调用
@import
。关于免费的思源黑体和思源宋体安装和使用。
下面再展示一下Xaringan slide个性化字体css文件(my-font.css)的代码设定(也可参看[说明]((https://github.com/yihui/xaringan/wiki/Deploy-Slides-Online)):
# my-font.css
@import url('https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap');
body { font-family:'Songti SC', serif, 'KaiTi', '楷体','Droid Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, 'Microsoft YaHei' ; }
h1, h2, h3 {
font-family: 'Ma Shan Zheng', cursive,'楷体';
font-weight: normal;
}
注意:
-
字体使用有先后顺序。客户浏览器会根据操作系统字体情况,依次按顺序来加载字体。
-
综合考虑不同平台和设备下的字体可用性。因此,往往需要设定字体库的“备胎计划”(fallback)。
此外,Xaringan中不同内容要素(elements)的字体应该考虑不同的设定,具体内容要素类别包括:
标题(headings):
h1,h2,h3,h4,...
代码区域(code chunk)以及行内代码(inline code):
.remark-code
和.remark-inline-code
表格(table):表题(caption),表注(notation)。
图片(figture):图题(caption),图注(notation)。
数学公式符号(latex equation and symbol):
5.4.8 后续需要处理的CSS问题
5.4.8.1 储备炫酷技能
提前准备好各类丰富slide功能的css实现方法。具体明确的一些炫酷功能,相关slide和css样板可以参看:
Remark.js推荐的三个Remark templates;尤其推荐Story模板Remark-Apron。
另外,有空还要好好看看
xaringanthemer
R包。Earo Wang’s slide展示了很多炫酷技巧,包括Javascript交互实现动画效果等。源代码见其github。
Yongfu Liao’s slide,提供了简单的xaringan使用介绍。其源代码github。
Emi Tanaka’s slide提供了关于页面布局的多种形式。
5.4.8.2 图文混排
图文混排技巧。
remark.js
自带光环的边栏效果(side bar).left-column[]
或者.right-column[]
。remark.js
自带光环的两栏效果(two columns).pull-left[]
或者.pull-right[]
。
5.4.8.3 Todo清单
页面布局。页面紧凑度和宽松度灵活调整。例如
remark-slide-content.roomy
。前导符设定。正文符号列表的前导符设定问题。
播放动画效果。常见的进入或退出等动画效果。CSS可以参考相对比较成熟的Animate.css,可以直接拿来就用。
窗格动画效果。大抵类似于PowerPoint的动画窗格设计,目前在Xaringan或remark.js里还没有看到。可以参看Earo Wang’s slide。以及另一个很不错的Xaringan slide报告题为Reproducible Data Workflows给出了绘制版流程图的动画效果,其背后的关键是连续的png部件是如何分解得到的(可参看其Rstudio cloud project)。有待进一步去找这样的draw工具,它应该能自动保存中间环节的png。
基于CSS的窗格动画Build your own universe。相关资源可以参看:Garrick Aden‑Buie的网站。
- 递进点击效果。可以参看Garrick Aden‑Buie的博文Better Progressive xaringan Slides with CSS and :last-of-type。其中通过CSS设计,实现递进点击效果。例如,bullets下最新一条醒目显示。
5.4.9 Tachyons CSS
因为使用R包xaringanExtra
的缘故,初次接触到Tachyons
。简单地,Tachyons
是一套创新的CSS架构理念和工具。
该CSS架构的可能最初设想,是来自前端开发员Adam Morse的一篇倡议性短文CSS and Scalability(他的个人首页)。然后经过实践探索和迭代坚持,诞生了目前的Tachyons
工具集。具体的介绍可以参看
Learn Tachyons。如果要使用各种css元件和样式,也可以登陆快速检索入口:Cheat Sheet。
这里主要说两个与本人项目相关的话题。
第一个话题是:为什么要尝试选择Tachyons
的CSS架构理念。其实也就是Tachyons
要解决的主要CSS痛点。个人认为最重要的优点有:1)坚持“所见即所得”。下面的图既是最好的说明。具体而言,它坚持明确的“语义化代码”,让CSS显性化,实现人类友好。2)坚持“乐高组装模块化”。基于最小颗粒的CSS原件和风格,可以进行无限可能的模块化组合,从而实现CSS代码可复用性和稳定性,以及维护的简单化。3)坚持“函数化CSS开发”。与R语言类似的函数化编程思维一致,可以通过参数进行灵活控制。例如其中提到的“尺度化”(scale)概念,运用于字体大小(fontsize)、宽度(width)等。个人感觉类似于ggplot2
的数据化映射思路。
第二个话题是:如何将Tachyons
的CSS架构运用于Xaringan
的视觉输出设计中去?当然目前已经可以基于xaringanExtra
包进行引入,但是里面也还有很多需要有效衔接的地方。
5.4.10 最后的若干思考和感受
这次对Xaringan 又一次发起冲锋,直接缘由是《计量经济学》双一流课程团队的视频录制。团队里其他人都不用R和Rmarkdown,更不要提Xaringan slide了。大家仍旧还是基于PowerPoint准备和制作授课幻灯片,有的老师甚至操作系统还是win7,office套件还是2010版!所以只能我事先用powerpoint设定好ppt模板,大家各自拿去制作自己的授课ppt(其实大部分团队老师甚至连ppt母版也不会用)。考虑到我自己的实际需求,我是希望能同时兼顾自己使用xaringan 和团队其他老师使用ppt的一致性——当然是不能奢求最后两者视觉效果的完全一样!目前在Xaringan上的设定调整,基本上达到了ppt模板类似效果的80%左右。
事实上,Xaringan和ppt二者效果一致性的达成,并不是最大的挑战。基本上基于html的Xaringan slide,可以使用css技巧实现ppt里的几乎所有功能。而况Xaringan还有很多ppt无法实现的”现代的”以及”未来的”诸多功能!真正的挑战在于团队协作,尤其是对于非常技术守旧的团队(并不指技术之外的其他方面)。到此,我的基本态度就是:最低限度地在技术方面与其他人协作,重点是把协作任务下自己事情做完、基本ok即可!
当然,这里面也还有一个在协作冲突中推动自己不断学习进步的问题。显然,如果没有这次的协作录制课程,我肯定还是会一如往常地坚持”最小化学习”策略:也即如无实际所需,绝不去茫然学习所谓的各种知识技能。这一次,我充分认识到了CSS对于Xaringan甚至对于Html的重要性,并且看到了一些文档协作、协作和输出的”未来”趋势和走向!
5.5 Xaringan增强:若干辅助R包及工具
Xaringan生态正在不断扩展,也将会大大方便slide制作,提升slide美观度,增加slide的更多新功能。本文将持续关注相关增强辅助包和定制函数,包括xaringanthemer、xaringanBuilder和metathis等正在开发和维护中的R包,还有一些定制化的R函数。
其中,博文Making Extra Great Slides做出了基本的梳理。本文在此基础上做了进一步测试、对比和总结。
5.5.1 增强包1:xaringanExtra
R包xaringanExtra
确实是“包”如其名,提供了不少Xaringan功能增强,可以说是大大缓解了Xaingan用户的大部分痛点。
具体可以参看R包xaringanExtra
的说明文档,以及关注追踪其github repo。
整体来看,个人认为比较有用的增强功能包括:
Scribble。slide可以涂鸦啦。一句话点评:手写墨迹的保存需要手动浏览器打印,有点费手。白板(键盘B)状态下无法手写涂鸦,槽点还有,距离好用总差那么一丢丢。
Search。全域slide搜索功能。一句话点评:这个好,直接甩掉pptx几条街。
Clipboard。便于代码复制操作。一句话点评:码农一族的最爱,非码农表示不觉明厉。
Tile View。实现slide缩略图效果。一句话点评:pptx有的,咱也的有。
Editable。slide内容可编辑。一句话点评:必须指定可编辑内容域,功能实用性也不够明确。
其中,比较有意思的slide操作包括:
Animate.css。动画效果。一句话点评:类似pptx幻灯片动画效果(进入、退出),但不是部件(element)的动画效果。无论如何,聊胜于无。此外,尤其要注意css独立文件的依赖关系,上传个人站点(如netlify)需仔细考证。
Panelset。面板集效果。一句话点评:它有点类似于Xaringan自带的navigator导航效果(
.right-column[]
+.left-column
)。区别在于:前者面板是水平罗列,且只需在一个slide页面下完成(一个---
下);其优点是代码更少,结构更紧凑;最大的问题是pdf导出需要额外包来加持解决,其他不足还包括:slide页码下的代码特别多,不便于导航写内容;另外对math公式等支持还不完善(如裸的Rmarkdown数学表达式会无法显示,但是加上.small[]
字体大小类css修饰则可以显示)。后者则是垂直罗列,且需要在多个slide页面下完成(多个---
下);其优点是便于导航编写内容,且每个pannel天然就占一张slide,方便导出pdf;不足在于垂直罗列后,右侧展示空间被压缩。Broadcast。你讲你的slide,观众可自动实时跟随slide翻页。一句话点评:很炫酷的功能,但是国内网速和访问可达性还有待测试。
FreezeFrame。定格gif,免得它一直动。一句话点评:功夫是好功夫,不过都摆开了大架势秀舞姿了(gif嗨起来),还管得了台下观众头昏眼花么?
Webcam。调用摄像头,实现图中画效果。一句话点评:颜值后生美女们,定会喜大普奔吧。
Tachyons。大概包括了多种支持Xaringan的Tachyons“小部件”(参看Tachyons官网),如文本窗框(text box)。一句话点评:似乎普通的css设定也可以实现,这个有空再去推敲推敲其中有啥玄妙。
5.5.2 增强包2:xaringanBuilder
R包xaringanBuilder
(github repo)的目标是支持多种输出格式的Xaringan slide导出:
html
pdf
gif
pptx
mp4
png
social (png of first slide sized for sharing on social media)
xaringanBuilder
包的安装命令为:remotes::install_github("jhelvy/xaringanBuilder")
。
优点:
pdf和pptx两种格式导出是大多数人比较关心的。可以与其他导出方法比较,看哪一种方案的导出质量和速度更优。例如,pdf格式输出,感觉与后面提到的
xaringan_to_pdf()
过程和效果都很类似。同时支持多种格式输入和输出,还可以对“中间格式”进行处理。例如可以支持先导出为pdf,然后再进一步把pdf导出为pptx。
支持复杂形式Xaringan slide的多格式输出。例如
xaringanBuilder::build_pptx("03-slide-class/04-data-measuring.Rmd",complex_slides = T)
就可以实现对计面板集(panelsets)类型slide的完美输出。这个功能也即实现后面要提到的xaringan_to_pdf()
函数过程和效果,必须点赞!
槽点:
可能的多种包依赖关系。例如pptx格式需要依赖
officer
包。“伪”pptx格式输出。
xaringanBuilder::build_pptx("03-slide-class/04-data-measuring.Rmd",complex_slides = T)
的结果,pptx的每张幻灯片都只是png格式的图片而已。不过,这个槽点应该是能够预料到的(大家猜猜是为什么?因为Xaringan slide和pptx幻灯片的血统完全不一样啊!)。
5.5.2.1 pdf输出时数学公式显示异常
问题描述:如果直接使用chrome浏览器打印pdf,数学公式显示都是正常的(如同html预览效果)。但是使用xaringanBuilder::build_pdf()
函数进行pdf输出,则数学公式总是显示异常(非常小)。
尝试办法:
- 怀疑html转会效果更好,尝试
.Rmd
转pdf或者.html
转pdf,问题都依旧。
# from html to pdf
xaringanBuilder::build_pdf("03-slide-class/04-data-measuring-test.html","public/04-data-measuring-test.pdf", complex_slides = T, delay = 3)
# from Rmd to pdf
xaringanBuilder::build_pdf("03-slide-class/04-data-measuring-test.Rmd", complex_slides = T, delay = 2)
- 怀疑
MathJax.js
在线不稳定,尝试指定调用其他路径,问题依旧。
Rmarkdown的公式渲染主要有两种方式。 - 默认渲染:xaringan会自动调用
MathJax.js
(集成在Rstudio中)来渲染数学公式和符号。 - 本地渲染:需要在yaml区域指定本地路径下或其他网络地址的MathJax.js
文件。
---
output:
xaringan::moon_reader:
chakra: libs/remark-latest.min.js
mathjax: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML.js"
self_contained: false
---
5.5.3 增强包3:xaringanthemer
R包xaringanthemer
提供了很多Xaringan slide风格的模板,具体可以查看官方说明,以及github repo。实际上我个人基本上还没有使用上述任何style,因为目前有自己的定制化xaringan模板。
简单点评:
以满足个性化需求为首,切记千篇一律。style风格一事,不过是外貌形象而已,仁者见仁智者见智。大部分人的工作汇报场景应该是固定化、模式化的,因此自己设计和维护的个性化style反而会更加实用,细节操控自然也会心中有数,迭代更新相应也更加可靠。
简单的就是最有力的。还是那句老话,越复杂的style、越多的新结构,也意味着更加难以控制。开源世界里采用或拥抱某些创新工具的基本法则应该是:简单可靠,步步为营。
5.5.3.1 输出pdf函数xaringan_to_pdf()
显然,对Xaringan进行功能增强以后,带来的直接后果就是slide的结构和形式开始变得复杂多样。
其中,使用xaringanExtra
设计面板集(panelsets)类型的slide时,简单使用chrome浏览器导出为pdf文件会不满足用户需求:pdf只会保留面板集slide下的第一个panel页面。
为此,xaringanExtra
包的开发者Garrick在博文”Printing xaringan slides with chromote“中,专门提到了这一用户需求和解决办法。他编写了一个输出pdf的R函数xaringan_to_pdf()
,并且后续可能会直接添加到xaringanExtra
包中去。xaringan_to_pdf()
函数源代码下载链接github Gist。
根据作者说明,xaringan_to_pdf()
函数需要依赖如下工具和R包:
本地浏览器Google Chrome
依赖包
chromote
:安装remotes::install_github("rstudio/chromote")
。其他依赖包:安装
install.packages(c("progress", "jsonlite", "pdftools", "digest"))
最后做一下简单点评:
pdf输出速度不太理想。
xaringan_to_pdf()
函数的pdf输出速度相对较慢,经测试180页slide大概需要5-10分钟(当然,根据slide的复杂程度会有一定差异)。这显然是因为依赖包过多或者工作流workflow过长 。限制是对html文件格式的pdf输出。例如
xaringan_to_pdf("03-slide-class/04-data-measuring.html")
,不能直接针对.Rmd
文件。相当于工作流workflow进一步被延长了。后续更新支持不确定。
5.5.4 增强工具1 :参考文献列表
温馨提示:目前R包
RefManageR
(version 1.1.0及以上)可以支持在Xaringan中实现我们提到的下述需求。不再需要后面的破解方法。
有些时候, presentation slide的最后需求列出幻灯片演讲中出现的参考文献列表。
问题在于Xaringan slide基于remark.js,而后者并不原生支持文献引用(bib citations)(参看yihui关于这一点的评论)。
下面将介绍两种破解思路和方法,但是其背后都基于如下过程:
保存文献格式文件
.bib
(最简单的就是采用文献管理软件zetero自动化保存)Rmarkdown文件中,使用特定R包(例如
RefManageR::ReadBib()
)读取上述.bib
文件,并渲染。根据需要开发定制函数,以实现特定显示效果(如列表太长时指定分页等)。
最新方法:使用RefManageR
(version 1.1.0及以上),具体参看Xaringan Bibliography and citations’ wiki page
- 步骤1:准备bib
```{r, load_refs, include=FALSE, cache=FALSE}
library(RefManageR)
BibOptions(check.entries = FALSE,
bib.style = "authoryear",
cite.style = "alphabetic",
style = "markdown",
hyperlink = FALSE,
dashed = FALSE)
myBib <- ReadBib("./myBib.bib", check = FALSE)
```
步骤2:在正文引用,使用
Citet()
,Citep()
,AutoCite()
。步骤3:参考文献列表(单页或分页)
# References
```{r all, echo=FALSE, results="asis"}
PrintBibliography(myBib)
```
# References
```{r split, echo=FALSE, results="asis"}
PrintBibliography(myBib, start = 1, end = 7)
```
破解方法1:适合参考文献条目较少的情形,直接读取.bib
条目并渲染。此时,全部文献条目将显示在一页slide上(示例效果可参看)。
```{r,split=FALSE,echo=FALSE,results='asis'}
knitr::write_bib(c(.packages()), "assets/packages.bib")
BibOptions(check.entries = TRUE, # style
bib.style = "authoryear",
sorting = "nty",
style = "markdown",
dashed = TRUE)
RefManageR::ReadBib("assets/packages.bib")
```
破解方法2:适合参考文献条目较多的情形,可以在多个slide上分页渲染文献条目(示例效果可参看jvcasillas的示例以及hhp的slide)。
如前所述,破解方法2需要设定一个定制函数以实现指定分页。github仓库jvcasillas/xaringan_bib
(参看)开发了这样的定制函数print_bib_rmd ()
(原始函数请参看)。具体的函数使用方式为:
```{r}
source(here::here("helper.R"))
library(RefManageR)
BibOptions(check.entries = FALSE,
bib.style = "authoryear",
style = "markdown",
dashed = TRUE)
file.name <- system.file(
"Bib",
"biblatexExamples.bib",
package = "RefManageR")
bib <- ReadBib(file.name)
```
显示第1页
```{r, results='asis', echo=FALSE, warning=FALSE}
print_bib_rmd(bib, start = 1, stop = 6)
```
显示第2页
```{r, results='asis', echo=FALSE, warning=FALSE}
print_bib_rmd(bib, start = 7, stop = 10)
```
5.6 Xaringan宏定制:remark.js Macros
5.6.1 定制宏:基本原理与使用方法
remark.js允许用户自定义宏。
自定义宏在markdown中的具体使用方法为:
![:macroName arg1, arg2, ...]
或者
![:macroName arg1, arg2, ...](this)
例如,可以自定义一个名为scale
的宏(在渲染remark之前,设定图片的缩放比例),其代码如下(具体参看):
remark.macros.scale = function (percentage) {
var url = this;
return '<img src="' + url + '" style="width: ' + percentage + '" />';
};
然后在Rmd文件的yaml区域调用这个宏:
在Rmarkdown正文中使用方法为:
![:scale 50%](image.jpg)
最终渲染结果的html格式为:
<img src="image.jpg" style="width: 50%" />
5.7 Xaringan杂音:常见异常及bug
5.7.1 杂音1:css相对路径失效问题
经验法则:为了得到正确的相对路径关系,我们需要:a.更新rmarkdown包;b.尽量使用Xaringan插件渲染
.Rmd
文件(“Rstudio \(\rightarrow\) Addins \(\rightarrow\) Infinite Moon Reader”!
一般情况下,Xaringan创作者会把CSS文件放在一个独立文件夹下,而不是与.Rmd文件并行存放。这样处理的重要理由在于:CSS文件往往是可复用的。
例如,下面的文件管理方式:
library(data.tree)
path <- c(
"master-SEM/mycss/my-custom-for-video-roomy.css",
"master-SEM/slide-chn-part1/part00-slide-intro.Rmd",
"master-SEM/slide-chn-part1/part00-slide-intro.html",
"master-SEM/slide-chn-part1/part00-slide-intro_files" )
(mytree <- data.tree::as.Node(data.frame(pathString = path)))
levelName
1 master-SEM
2 ¦--mycss
3 ¦ °--my-custom-for-video-roomy.css
4 °--slide-chn-part1
5 ¦--part00-slide-intro.Rmd
6 ¦--part00-slide-intro.html
7 °--part00-slide-intro_files
同时,Xaringan slide最常见使用场景一般也有两个:
项目内(项目A)将
.Rmd
代码文件渲染为.html
演示文件,将项目上线(如github),然后分享演讲内容的链接。其他项目(项目B,如netlify静态建站项目),需要调用上述项目的
.html
演示文件。
然而对于后者而言,CSS文件夹或html文件夹的移动或复制(如netlify静态建站时需要拷贝到static/
文件下)则会面临相对引用路径的问题。而且这也是一个Xaringan
包已知的“旧疾隐患”(参看Relative paths to dir above root? see xaringan issue)。
好在最近Xaringan团队着手处理了这个“定时炸弹”。具体请参看:Relative CSS in parent folder are now added with an absolute path (see xaringan issue)。然而通过测试,也发现目前只是“部分地”解决了问题。
操作情形1:如果使用Rstudio菜单渲染.Rmd
文件(“Rstudio \(\rightarrow\) knit \(\rightarrow\) knit to moon_reader”),输出的.html
文件与css文件的路径关系结果显示不正常!使用chrome浏览器 \(\rightarrow\) 右键“查看”,具体关系如下:
<!---
scenario 1: knit button by 'knit to moon_reader'
html source element in chrome
--->
<head>
<style>
<link rel="stylesheet" href="D:/github/master-SEM/mycss/my-custom-for-video-roomy.css" type="text/css">
</style>
</head>
然而href
后面的css路径”D:/github/master-SEM/mycss/my-custom-for-video-roomy.css” ,仅仅只是“显示路径”。chrome浏览器下把鼠标悬置1秒在上述“显示路径”上,则可以看到css的“真实路径”为:
“file:///D:/github/master-SEM/slide-chn-part1/D:/github/master-SEM/mycss/text-box.css”。显然这样的路径关系是“不正常”的!
操作情形2:如果使用Xaringan插件渲染.Rmd
文件(“Rstudio \(\rightarrow\) Addins \(\rightarrow\) Infinite Moon Reader”),输出的.html
文件与css文件的路径关系结果则显示正常。使用chrome浏览器 \(\rightarrow\) 右键“查看”,具体关系如下:
<!---
scenario 2: Addins by 'Infinite Moon Reader'
html source element in chrome
--->
<head>
<style>
<link rel="stylesheet" href="../mycss/my-custom-for-video-roomy.css" type="text/css">
</style>
</head>
可以观察到href
后面的css文件的“显示路径”为”../mycss/my-custom-for-video-roomy.css” 。进一步地,在chrome浏览器下把鼠标悬置1秒在上述“显示路径”上,则可以看到css的“真实路径”为:file:///D:/github/master-SEM/mycss/text-box.css
。而这样的路径关系应该是“正常”的!
5.7.2 杂音2:count: false/true
经验法则:目前没有找到好的解决办法,建议只在幻灯片的首页设定”count: false”,第2页开始立刻设定为”count: true”。——免得夜长梦多!
先简单描述一下问题:多个幻灯片中设定了count: false/true
,输出的.html
一切如你所愿,然而当转换为pdf时(具体地,是使用pagedown::chrome_print("your-output-slide.html")
进行pdf转换),部分设定为count: false
的幻灯片会消失不见!
例如,.Rmd
里的slide 代码如下。对输出的.html进行pdf转换(pagedown::chrome_print()
)后,pdf仅仅只有第3页,前两页会消失不见!
<!---
scenario:
1.multiple slides use class of "count: false/true"
2. convert .html to pdf by using pagedown::chrome_print("your-output-slide.html")
--->
---
count: true
Content 1
---
count: false
Content 2
---
count: false
Content 3
参看资料:
- Slides written in Rmd missing pages when converting from HTML to PDF see stackoverflow。
5.7.3 杂音3:html/pdf转可编辑化的pptx
温馨提示:严格一致的可编辑性的pptx输出基本难以实现,无论是
Bluebeam revu extreme
软件手动导出,还是LibreOffice
软件的CMD命令导出。
html格式的slide适合展示,但是学生可能更喜欢.pdf或者.pptx格式的slide。如果单纯只是获得图片格式的pptx,这个基本没有什么实现难度,例如pagedown
。问题在于严格一致的可编辑性的pptx输出(文本、图片要素等可编辑或拉选移动),理论上基本是很难实现的。
具体地,实现可编辑ppt的方法至少有:
利用
Bluebeam revu extreme
软件手动将pdf导出为pptx。利用
LibreOffice
软件将pdf导出为pptx(见下),这里可以使用CMD命令方法进行批量处理。
相关操作可参看:
html转pdf的一个选择DeckTape(支持reveal /remark等多种编译方法)。
LibreOffice
是pdf转可编辑化的pptx的一个选择。可以参看博文:Automated Build and Publication of Slides with R Markdown, Reveal.js, DeckTape, and LibreOffice.
这里重点介绍LibreOffice
软件的Linux命令操作:
# 在CMD中运行如下代码
soffice --infilter="impress_pdf_import" --convert-to pptx:"Impress MS PowerPoint 2007 XML" d:/opensource-getting-involved_2.pdf
# 同名的pptx转换文件会出现在 `c:/user/your/`路径下
已经完成的导出测试包括:
reveal格式输出pdf下的pptx导出。
remark格式输出pdf下的pptx导出。