reveal.js简介

reveal.js 是一个开源的 HTML 展示框架。我们可以使用它做出各种精美的幻灯片,和传统的 PPT 不同,reveal.js 需要在浏览器中运行,并且可以把 Markdown 文件转为类似 PPT 的演示文稿,轻快省力,减少排版上的时间,更专于文字内容,同时也获得 PPT 所不具有的灵活性。

安装教程

reveal.js 的官网有详细说明,一般的安装/启动步骤如下:

  1. git clone https://github.com/hakimel/reveal.js.git

  2. cd reveal.js && npm install

  3. npm start

  4. 打开 http://localhost:8000/ 即可预览

自定义端口启动:npm start -- --port=8008

使用教程

简介

用 vscode 打开/reveal.js/index.html,这是一个简单的样例,只有两页 slides,分别显示“Slide 1”和“Slide 2”:

 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
31
32
33
34
35
36
37
38
39
40
41
42
43
<!doctype html>
<html lang="en">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

	<title>reveal.js</title>

	<link rel="stylesheet" href="dist/reset.css">
	<link rel="stylesheet" href="dist/reveal.css">
	<link rel="stylesheet" href="dist/theme/black.css">  <!-- 主题 -->

	<!-- Theme used for syntax highlighted code -->
	<link rel="stylesheet" href="plugin/highlight/monokai.css">
</head>

<body>
	<div class="reveal">
		<div class="slides">
			<section>Slide 1</section>
			<section>Slide 2</section>
		</div>
	</div>

	<script src="dist/reveal.js"></script>
	<script src="plugin/notes/notes.js"></script>
	<script src="plugin/markdown/markdown.js"></script>
	<script src="plugin/highlight/highlight.js"></script>
	<script>
		// More info about initialization & config:
		// - https://revealjs.com/initialization/
		// - https://revealjs.com/config/
		Reveal.initialize({
			hash: true,

			// Learn about plugins: https://revealjs.com/plugins/
			plugins: [RevealMarkdown, RevealHighlight, RevealNotes]
		});
	</script>
</body>

</html>

在 index.html 里,可以看到一对<body></body>之间嵌套了一对<div class="reveal"></div>,而<div class="slides"></div>之间的内容对应页面显示的内容。

分页

reveal.js 有两种页面类型,横向的一级页面、纵向的子页面。后者务必嵌套在前者里面。键盘上的左右箭头控制一级页面,上下键移动子页面。

reveal.js 分页演示

对应的代码为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<div class="reveal">
    <div class="slides">
        <section>Welcome ~</section> <!-- 一级页面 -->
        <section>
            <section>你好!</section> <!-- 子页面 -->
            <section>Hello World!</section>
        </section>
        <section>
            《西游记》
            <section>第一回 灵根育孕源流出 心性修持大道生</section>
            <section>第二回 悟彻菩提真妙理 断魔归本合元神</section>
        </section>
    </div>
</div>

分段显示

如果需要在演示时分段显示,可以使用:

1
2
3
4
5
6
<section>
    <p class="fragment" style="font-size: larger;">《泊秦淮》</p>
    <p class="fragment" style="font-size: smaller;">杜牧</p>
    <p class="fragment">&nbsp;烟笼寒水月笼沙,夜泊秦淮近酒家。</p>
    <p class="fragment">&nbsp;商女不知亡国恨,隔江犹唱后庭花。</p>
</section>
reveal.js 分段显示

支持 markdown 语法

reveal.js 支持简单的 markdown 的写法,在<section> 标签里添加data-markdown 属性,表示该段内容用 markdown 引擎解析:

reveal.js markdown演示
对应的代码为:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="reveal">
    <div class="slides">
        <section>
            <section data-markdown>
                ### 怎么把大象放进冰箱?
                > How to put an elephant in the refrigerator?

                ![](/Users/yuki/Pictures/elephant_icon.png)
                1. 打开冰箱门;
                2. 放入大象;
                3. 关上冰箱门。
                ---
                | 左对齐标题 | 右对齐标题 | 居中对齐标题 |
                | :------| ------: | :------: |
                | 短文本 | 中等文本 | 稍微长一点的文本 |
                | 稍微长一点的文本 | 短文本 | 中等文本 |
            </section>
        </section>
    </div>
</div>

背景

支持使用<section data-background="">设置不同颜色的背景:

1
2
3
<section data-background="#F0FFF0">
    This page's color called <b>Honeydew</b>.
</section>

可以使用图片背景:

1
2
3
4
<section data-background-image="/Users/yuki/Pictures/95698585_p0_master1200.jpeg">
    <h3 style="background-color: rgba(0, 0, 0, 0.8);">その可憐な少女は魔女であり、旅人でした。 ―― そう、私です。</h3>
    <blockquote style="color: gray; background-color: rgba(0, 0, 0, 0.8);">请别在意,我是个旅人,得继续旅行才行。</blockquote>
</section>
reveal.js 图片背景

甚至可以使用视频作为背景:

1
2
3
<section data-background-video="https://oss.ppter8.com/lobZ-1_HVl-QWpIZr6NhlBAVOajm-1050x.mp4">
    This page's video video background from <a href="https://oss.ppter8.com/lobZ-1_HVl-QWpIZr6NhlBAVOajm-1050x.mp4">PPTer</a>.
</section>
reveal.js 视频背景

自动动画

有些幻灯片中我们想实现如渐变、滑动、新增或者删除元素等动画效果。reveal.js 会自动为幻灯片中的元素设置动画效果,我们需要做的就是在相邻的两页section元素上添加data-auto-animate属性,这样 reveal.js 会为所有匹配的元素设置动画:

 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
<section>
    <section data-auto-animate>
        <h3>reveal.js 的优点</h3>
    </section>
    <section data-auto-animate>
        <h3>Reveal.js的优点</h3>
        <ul>
            <li>界面优美</li>
            <!-- <li> 元素表示列表里的条目。它必须包含在一个父元素里:一个有序列表 (<ol>),一个无序列表 (<ul>),或者一个菜单 (<menu>)。 -->
        </ul>
    </section>
    <section data-auto-animate>
        <h3>Reveal.js的优点</h3>
        <ul>
            <li>界面优美</li>
            <li>运行简单</li>
        </ul>
    </section>
    <section data-auto-animate>
        <h3>Reveal.js的优点</h3>
        <ul>
            <li>界面优美</li>
            <li>运行简单</li>
            <li>功能强大</li>
        </ul>
    </section>
</section>
reveal.js 自动动画演示

自动动画标签

对于图片、视频和 iframe 等多媒体元素,reveal.js 通过比较他们的 src 属性来自动匹配相同的元素,即相邻的幻灯片,文本内容改变了(比如上面第二张幻灯片“界面优美”→“界面好看”),那么动画效果就会失效。我们可以在元素上添加data-id属性来强制进行动画效果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- 自动动画标签 -->
<section>
    <section data-auto-animate>
        <h2>自动动画</h2>
    </section>

    <section data-auto-animate>
        <h2 data-id="tag_1" style="text-align: left; color: rgb(0, 255, 94);">自动动画 1</h2>
    </section>

    <section data-auto-animate>
        <h2 data-id="tag_1" style="text-align: right; color: rgb(87, 87, 212);">自动动画 2</h2>
    </section>
</section>
reveal.js 自动动画标签演示

我们看到第一个动画到第二个动画之间,由于自动匹配失效,因此没有动画;第二个动画到第三个动画之间由于我们强制加上了data-id属性,因此动画效果依然是生效的。

自动动画ID

有时候我们会存在多个动画,相邻的动画有可能会互相干扰,可以通过data-auto-animate-iddata-auto-animate-restart对动画进行分组。我们可以对相邻分组的幻灯片上加上data-auto-animate-id属性,属性的值可以是任意的,相同组保证值相同即可;这样,相邻的幻灯片会识别相同的id进行动画效果。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 自动动画ID -->
<section>
    <section data-auto-animate data-auto-animate-id="one">
        <h1 style="color: white;">第一组动画</h1>
    </section>
    <section data-auto-animate data-auto-animate-id="one">
        <h1 style="color: #3B82F6;">第一组动画</h1>
    </section>

    <section data-auto-animate data-auto-animate-id="two">
        <h1 style="color: white;">第二组动画</h1>
    </section>
    <section data-auto-animate data-auto-animate-id="two">
        <h1 style="color: #10B981;">第二组动画</h1>
    </section>

    <section data-auto-animate data-auto-animate-id="three">
        <h1 style="color: white;">第三组动画</h1>
    </section>
    <section data-auto-animate data-auto-animate-id="three">
        <h1 style="color: #EC4899;">第三组动画</h1>
    </section>
</section>
reveal.js 自动动画ID演示

如果同一组的幻灯片比较多,我们需要加上很多的 id,上面的方式显得比较繁琐。因此 reveal.js 提供另一种控制动画的方式:data-auto-animate-restart属性;这个属性会阻止上一张幻灯片和本组幻灯片之间的动画效果(即使他们有相同的 id):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 自动动画ID(方法2) -->
<section>
    <section data-auto-animate>
        <h1 style="color: white;">第一组动画</h1>
    </section>
    <section data-auto-animate>
        <h1 style="color: #3B82F6;">第一组动画</h1>
    </section>

    <section data-auto-animate data-auto-animate-restart> <!-- id restart -->
        <h1 style="color: white;">第二组动画</h1>
    </section>
    <section data-auto-animate>
        <h1 style="color: #10B981;">第二组动画</h1>
    </section>

    <section data-auto-animate data-auto-animate-restart> <!-- id restart -->
        <h1 style="color: white;">第三组动画</h1>
    </section>
    <section data-auto-animate>
        <h1 style="color: #EC4899;">第三组动画</h1>
    </section>
</section>

代码

reveal.js 使用 highlight.js 来支持代码高亮。可以直接写<pre><code></code></pre>标签来实现, data-trim表示去除多余的空格,data-line-numbers表示突出显示,data-noescape 来避免自动转义。这里代码块是套在<script type='text/html' style='display:block'></script>中间,以防代码格式异常(根据实际情况选择使用)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 代码 -->
<section>
    <pre><code class="hljs cpp" data-trim data-line-numbers="5-7" data-noescape>
        <script type='text/html' style='display:block'>// 使用返回 tuple 和 decomposition declarations 语法来模拟 Go 语言函数多返回值功能
        #include <iostream>
        #include <tuple>

        std::tuple<std::string, bool> foo() {
            return std::make_tuple("hello", true);
        }

        int main() {
            auto [val, flag] = foo();
            if (flag) {
                std::cout << val << endl; 
            } 
            return 0; 
        }
        </script>
    </code></pre>
</section>
reveal.js 代码显示

数学公式

  1. 导入脚本:

    1
    
    <script src="plugin/math/math.js"></script>
    
  2. 初始化设置:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    Reveal.initialize({
        math: {
            mathjax: 'https://cdn.jsdelivr.net/gh/mathjax/mathjax@2.7.8/MathJax.js',
            config: 'TeX-AMS_HTML-full',
            TeX: {
                Macros: {
                    RR: "{\\bf R}"
                }
            }
        },
        plugins: [RevealMath]
    });
    
  3. 代码:

    1
    2
    3
    4
    5
    6
    7
    
    <!-- 公式 -->
    <section>
        <a style="font-family: 'Times New Roman', Times, serif; color: white;">
            $$ \lim_{x \to \infty} x^2_{22} - \int_{1}^{5}x\mathrm{d}x + \sum_{n=1}^{20} n^{2} = \prod_{j=1}^{3}
            y_{j} + \lim_{x \to -2} \frac{x-2}{x} $$
        </a>
    </section>
    
reveal.js 数学公式

其他

  1. 浏览器播放幻灯片时,按“ECS”进入视图模式;

  2. 浏览器播放幻灯片时,按“B”暂停播放(熄灭屏幕);

  3. 默认的字体普遍偏大,可以在/reveal.js/dist/theme/目录下更改;

  4. 在演说时,会用到注释,对于注释,可以通过<aside class="notes">来实现:

    1
    2
    3
    
    <aside class="notes">
      这里是注释。
    </aside>
    

    在幻灯片页面,按下s键,就可以调出注释页面,注释页面包含了当前幻灯片、下一章幻灯片、注释,以及幻灯片播放时间。

  5. 更多功能请参考/reveal.js/demo.html以及 reveal.js 的官网/Github,本文介绍的 reveal.js 的功能源文件如下:

    代码
      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
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    
    <!doctype html>
    <html lang="en">
    
    <head>
    	<meta charset="utf-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    
    	<title>reveal.js</title>
    
    	<link rel="stylesheet" href="dist/reset.css">
    	<link rel="stylesheet" href="dist/reveal.css">
    	<link rel="stylesheet" href="dist/theme/dracula.css">
    
    	<!-- Theme used for syntax highlighted code -->
    	<link rel="stylesheet" href="plugin/highlight/monokai.css">
    </head>
    
    <body>
    	<div class="reveal">
    		<div class="slides">
    			<section>
    				<p class="fragment" style="font-size: larger;">《泊秦淮》</p>
    				<p class="fragment" style="font-size: smaller;">杜牧</p>
    				<p class="fragment">&nbsp;烟笼寒水月笼沙,夜泊秦淮近酒家。</p>
    				<p class="fragment">&nbsp;商女不知亡国恨,隔江犹唱后庭花。</p>
    			</section>
    			<section>
    				<!-- markdown 写法 -->
    				<section data-markdown>
    					### 怎么把大象放进冰箱?
    					> How to put an elephant in the refrigerator?
    
    					![](/Users/yuki/Pictures/elephant_icon.png)
    					1. 打开冰箱门;
    					2. 放入大象;
    					3. 关上冰箱门。
    					---
    					| 左对齐标题 | 右对齐标题 | 居中对齐标题 |
    					| :------| ------: | :------: |
    					| 短文本 | 中等文本 | 稍微长一点的文本 |
    					| 稍微长一点的文本 | 短文本 | 中等文本 |
    				</section>
    			</section>
    			<!-- 背景颜色 -->
    			<section data-background="#F0FFF0">
    				This page's color called <b>Honeydew</b>.
    			</section>
    			<!-- 图片背景和不透明度调节 -->
    			<section data-background-image="/Users/yuki/Pictures/95698585_p0_master1200.jpeg">
    				<h3 style="background-color: rgba(0, 0, 0, 0.8);">その可憐な少女は魔女であり、旅人でした。 ―― そう、私です。</h3>
    				<blockquote style="color: gray; background-color: rgba(0, 0, 0, 0.8);">请别在意,我是个旅人,得继续旅行才行。</blockquote>
    			</section>
    			<!-- 视频背景 -->
    			<section data-background-video="https://oss.ppter8.com/lobZ-1_HVl-QWpIZr6NhlBAVOajm-1050x.mp4">
    				This page's video video background from <a
    					href="https://oss.ppter8.com/lobZ-1_HVl-QWpIZr6NhlBAVOajm-1050x.mp4">PPTer</a>.
    			</section>
    			<!-- 自动动画 -->
    			<section>
    				<section data-auto-animate>
    					<h3>reveal.js 的优点</h3>
    				</section>
    				<section data-auto-animate>
    					<h3>Reveal.js的优点</h3>
    					<ul>
    						<li>界面优美</li>
    						<!-- <li> 元素表示列表里的条目。它必须包含在一个父元素里:一个有序列表 (<ol>),一个无序列表 (<ul>),或者一个菜单 (<menu>)。 -->
    					</ul>
    				</section>
    				<section data-auto-animate>
    					<h3>Reveal.js的优点</h3>
    					<ul>
    						<li>界面优美</li>
    						<li>运行简单</li>
    					</ul>
    				</section>
    				<section data-auto-animate>
    					<h3>Reveal.js的优点</h3>
    					<ul>
    						<li>界面优美</li>
    						<li>运行简单</li>
    						<li>功能强大</li>
    					</ul>
    				</section>
    			</section>
    			<!-- 自动动画标签 -->
    			<section>
    				<section data-auto-animate>
    					<h2>自动动画</h2>
    				</section>
    
    				<section data-auto-animate>
    					<h2 data-id="tag_1" style="text-align: left; color: rgb(0, 255, 94);">自动动画 1</h2>
    				</section>
    
    				<section data-auto-animate>
    					<h2 data-id="tag_1" style="text-align: right; color: rgb(87, 87, 212);">自动动画 2</h2>
    				</section>
    			</section>
    			<!-- 自动动画ID -->
    			<section>
    				<section data-auto-animate data-auto-animate-id="one">
    					<h1 style="color: white;">第一组动画</h1>
    				</section>
    				<section data-auto-animate data-auto-animate-id="one">
    					<h1 style="color: #3B82F6;">第一组动画</h1>
    				</section>
    
    				<section data-auto-animate data-auto-animate-id="two">
    					<h1 style="color: white;">第二组动画</h1>
    				</section>
    				<section data-auto-animate data-auto-animate-id="two">
    					<h1 style="color: #10B981;">第二组动画</h1>
    				</section>
    
    				<section data-auto-animate data-auto-animate-id="three">
    					<h1 style="color: white;">第三组动画</h1>
    				</section>
    				<section data-auto-animate data-auto-animate-id="three">
    					<h1 style="color: #EC4899;">第三组动画</h1>
    				</section>
    			</section>
    			<!-- 自动动画ID(方法2) -->
    			<section>
    				<section data-auto-animate>
    					<h1 style="color: white;">第一组动画</h1>
    				</section>
    				<section data-auto-animate>
    					<h1 style="color: #3B82F6;">第一组动画</h1>
    				</section>
    
    				<section data-auto-animate data-auto-animate-restart> <!-- id restart -->
    					<h1 style="color: white;">第二组动画</h1>
    				</section>
    				<section data-auto-animate>
    					<h1 style="color: #10B981;">第二组动画</h1>
    				</section>
    
    				<section data-auto-animate data-auto-animate-restart> <!-- id restart -->
    					<h1 style="color: white;">第三组动画</h1>
    				</section>
    				<section data-auto-animate>
    					<h1 style="color: #EC4899;">第三组动画</h1>
    				</section>
    			</section>
    			<!-- 代码 -->
    			<section>
    				<pre><code class="hljs cpp" data-trim data-line-numbers="5-7" data-noescape>
    					<script type='text/html' style='display:block'>// 使用返回 tuple 和 decomposition declarations 语法来模拟 Go 语言函数多返回值功能
    					#include <iostream>
    					#include <tuple>
    					
    					std::tuple<std::string, bool> foo() {
    					    return std::make_tuple("hello", true);
    					}
    			
    					int main() {
    					    auto [val, flag] = foo();
    					    if (flag) {
    					        std::cout << val << endl; 
    					    } 
    					    return 0; 
    					}
    					</script>
    				</code></pre>
    			</section>
    			<!-- 公式 -->
    			<section>
    				<a style="font-family: 'Times New Roman', Times, serif; color: white;">
    					$$ \lim_{x \to \infty} x^2_{22} - \int_{1}^{5}x\mathrm{d}x + \sum_{n=1}^{20} n^{2} = \prod_{j=1}^{3}
    					y_{j} + \lim_{x \to -2} \frac{x-2}{x} $$
    				</a>
    			</section>
    		</div>
    	</div>
    
    	<script src="dist/reveal.js"></script>
    	<script src="plugin/notes/notes.js"></script>
    	<script src="plugin/markdown/markdown.js"></script>
    	<script src="plugin/highlight/highlight.js"></script>
    	<script src="plugin/math/math.js"></script>
    
    	<script>
    		// More info about initialization & config:
    		// - https://revealjs.com/initialization/
    		// - https://revealjs.com/config/
    		Reveal.initialize({
    			math: {
    				mathjax: 'https://cdn.jsdelivr.net/gh/mathjax/mathjax@2.7.8/MathJax.js',
    				config: 'TeX-AMS_HTML-full',
    				TeX: {
    					Macros: {
    						RR: "{\\bf R}"
    					}
    				}
    			},
    			hash: true,
    			controls: true,       // 在右下角显示控制面板
    			slideNumber: true,   // 显示幻灯片页码,可使用代码 slideNumber: 'c/t',表示 '当前页/总页数'
    			// Learn about plugins: https://revealjs.com/plugins/
    			plugins: [RevealMarkdown, RevealHighlight, RevealNotes, RevealMath]
    		});
    	</script>
    </body>
    
    </html>
    

【参考】:

  1. Reveal.js:把你的 Markdown 文稿变成 PPT

  2. 网页幻灯片演示框架:Reveal.js

  3. HTML5幻灯片库reveal.js使用