利用 revealjs 快速写出漂亮的 PPT

背景

日常工作汇报、演讲经常需要制作PPT,一般使用这些标准工具 Microsoft PowerPointApple KeynoteGoogle Slides 。但这些工具对我来说过于繁琐,我希望有一个简单且支持 markdown 的工具,很幸运我找到了RevealJS,它是一个开源的 HTML 幻灯片框架,制作出精美的PPT,对于web开发人员来说更是首选。

入门

reveal.js 使用 nodejs 构建,需要提前安装好 nodejs。下载启动访问http://localhost:8000 就可以看到一个演示PPT。

git clone git@github.com:hakimel/reveal.js.git
mv reveal.js slides-demo
cd slides-demo
npm install
npm start

使用 Vscode 打开 index.html 制作,一个 section 就是一页幻灯片。

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

每张幻灯片是从左到右线性切换,如果需要在同一页垂直过渡切换,可以嵌套section

        <div class="reveal">
            <div class="slides">
                <section>Slide 1</section>
                <section>
                        <p>这里有一些内容</p>
                        <section>1</section>
                        <section>2</section>
                        <section>2</section>
                </section>
            </div>
        </div>

添加 data-background 可以给幻灯片添加一个背景。

<section data-background="https://blogs-on.oss-cn-beijing.aliyuncs.com/imgs/202206201857325.jpeg">
  <h2>来吧!展示</h2>
</section>

添加 fragment 设置内容动画,每次展示一个内容。比如以此呈现列表,只需添加 class="fragment".

<section>
  <h2>片段顺序</h2>
  <ul>
    <li class="fragment">第一个</li>
    <li class="fragment">第二个</li>
    <li class="fragment">最后一个</li>
  </ul>
</section>

添加图片,在项目里创建 assets 目录存放图片,然后引入。

<section>
  <h2>插入</h2>
  <img src="assets/img.png" alt="img">
</section>

Reveal-md

直接编辑 Html 比较麻烦,我还是习惯在 markdown 里编辑内容。使用reveal-md 可以将 markdown 转换成 Html,或导出PDF。

安装

npm install -g reveal-md

npm 6.x 版本安装会出现权限错误,需要添加 --unsafe-perm=true

sudo npm install -g reveal-md --unsafe-perm=true

--unsafe-perm=true:“false if running as root, true otherwise”,大体意思是 npm 的安全限制,root身份运行时不会查询 root 的上下文,所以 sudo 运行时还需要指定 --unsafe-perm=true 来忽略这种限制。

相关命令

# 启动
reveal-md slides.md -w 
# 生成 Html 默认目录_static
reveal-md slides.md --static
# 生成 Html 默认目录_static,指定图片目录 assets
reveal-md slides.md --static --static-dirs=assets
# 导出PDF
reveal-md slides.md --print slides.pdf
reveal-md slides.md --print slides.pdf --print-size 1024x768
reveal-md slides.md --print slides.pdf --print-size A4

幻灯片主题

默认主题

名称 效果
black 黑色背景,白色文本,蓝色链接(默认)
white 白色背景,黑色文本,蓝色链接
league 灰色背景,白色文字,蓝色链接
beige 米色背景,深色文字,棕色链接
sky 蓝色背景,细暗文本,蓝色链接
night 黑色背景,厚白色文字,橙色链接
serif 卡布奇诺背景,灰色文本,棕色链接
simple 白色背景,黑色文本,蓝色链接
solarized 高分辨率照片
blood 深色背景,厚白文字,红色链接
moon 高分辨率照片

自定义主题

  1. 下载 reveal git clone git@github.com:hakimel/reveal.js.git
  2. 在 /css/theme/coder.scss 中复制一个文件;
  3. 运行 npm run build -- css-themes 生成css dist/coder.css;
  4. 运行指定主题 reveal-md slides.md -w --theme theme/coder.css

切换时动画

名称 效果
none 瞬间切换背景
fade 交叉淡入淡出 - 背景转换的默认值
slide 在背景之间滑动 — 幻灯片过渡的默认设置
convex 以凸角滑动
concave 以凹角滑动
zoom 向上缩放传入的幻灯片,使其从屏幕中心向内扩展

配置

我们可以在Markdown文件里通过 yaml 进行配置

title: Slides # 幻灯片名称
theme: solarized # 幻灯片主题
highlightTheme: github # 代码高亮主题
revealOptions: 
  transition: 'convex' # 动画效果

reveal 其它配置项

{
  // 显示控制箭头
  controls: true,
  // 循环播放
  loop: false
  // 更多参考 https://revealjs.com/config/
}

reveal-md 其它配置项

{
  // 幻灯片横行切割标志
  "separator": "^\n\n\n",
  // 幻灯片垂直切割标志
  "verticalSeparator": "^\n\n"
}

用法

当需要在 section 中添加属性时,Markdown 的写法如下

<!-- .slide: 属性=属性值 -->

当需要在其它元素插入属性时,Markdown 的写法如下

<!-- .element: 属性=属性值 -->

一些例子,设置背景色或背景图

<!-- .slide: data-background="#fff" -->
<!-- .slide: data-background="./bg.png" -->
<!-- .slide: data-background-image="https://xxx.jpg" data-background-opacity=.1 data-background-repeat="no-repeat" -->

设置 fragment

- Item1 <!-- .element: class="fragment" data-fragment-index="1" -->
- Item2 <!-- .element: class="fragment fade-in-then-out" data-fragment-index="2" -->

指定代码的高亮顺序

```js [1-2|3|4|5]
let a = 1;
let b = 2;
let c = x => 1 + 2 + x;
c(3);
c(2);
```

地址跳转

<!-- .slide: id=0 -->
[跳转0](#/0)

部署到Netlify

我喜欢将一些静态html托管到netlify,它免费比较好用。先在 Github 创建一个仓库 coder_slides,然后创建如下目录

├── README.md
└── content
    ├── assets
    │   └── bg.jpeg
    ├── template
    │   ├── listing.html
    │   └── reveal.html
    └── coder.md
  • content 放MD文件集合;
  • assets 本地图片资源;
  • template 是渲染后的 HTML 模版,包含列表页面和详情页面,可以自行修改。

默认的 listing.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>{{pageTitle}}</title>
    <link rel="stylesheet" href="{{{themeUrl}}}" id="theme" />
  </head>

  <body>
    <ul>
      {{#files}}
      <li>
        <a href="{{filePath}}" title="{{title}}">
          {{#title}}{{.}} ({{filePath}}){{/title}}{{^title}}{{filePath}}{{/title}}
        </a>
      </li>
      {{/files}}
    </ul>
  </body>
</html>

默认的 reveal.html

<!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>{{{title}}}</title>
    {{#absoluteUrl}}
    <meta property="og:title" content="{{{title}}}" />
    <meta property="og:type" content="website" />
    <meta property="og:image" content="{{{absoluteUrl}}}/featured-slide.jpg" />
    <meta property="og:url" content="{{{absoluteUrl}}}" />
    {{/absoluteUrl}}
    <link rel="shortcut icon" href="{{{base}}}/favicon.ico" />
    <link rel="stylesheet" href="{{{base}}}/dist/reset.css" />
    <link rel="stylesheet" href="{{{base}}}/dist/reveal.css" />
    <link rel="stylesheet" href="{{{themeUrl}}}" id="theme" />
    <link rel="stylesheet" href="{{{base}}}{{{highlightThemeUrl}}}" />

    {{#cssPaths}}
    <link rel="stylesheet" href="{{{.}}}" />
    {{/cssPaths}}

    {{#watch}}

    <script>
      document.write(
        '<script src="http://' +
          (location.host || 'localhost').split(':')[0] +
          ':35729/livereload.js?snipver=1"></' +
          'script>'
      );
    </script>
    {{/watch}}
  </head>
  <body>
    <div class="reveal">
      <div class="slides">{{{slides}}}</div>
    </div>

    <script src="{{{base}}}/dist/reveal.js"></script>

    <script src="{{{base}}}/plugin/markdown/markdown.js"></script>
    <script src="{{{base}}}/plugin/highlight/highlight.js"></script>
    <script src="{{{base}}}/plugin/zoom/zoom.js"></script>
    <script src="{{{base}}}/plugin/notes/notes.js"></script>
    <script src="{{{base}}}/plugin/math/math.js"></script>
    <script>
      function extend() {
        var target = {};
        for (var i = 0; i < arguments.length; i++) {
          var source = arguments[i];
          for (var key in source) {
            if (source.hasOwnProperty(key)) {
              target[key] = source[key];
            }
          }
        }
        return target;
      }

      // default options to init reveal.js
      var defaultOptions = {
        controls: true,
        progress: true,
        history: true,
        center: true,
        transition: 'default', // none/fade/slide/convex/concave/zoom
        plugins: [
          RevealMarkdown,
          RevealHighlight,
          RevealZoom,
          RevealNotes,
          RevealMath
        ]
      };

      // options from URL query string
      var queryOptions = Reveal().getQueryHash() || {};

      var options = extend(defaultOptions, {{{revealOptionsStr}}}, queryOptions);
    </script>

    {{#scriptPaths}}
    <script src="{{{.}}}"></script>
    {{/scriptPaths}}

    <script>
      Reveal.initialize(options);
    </script>
  </body>
</html>

运行本地调试

reveal-md content/ --template template/reveal.html --listing-template template/listing.html
list

如何部署部署到netlify?

注册一个netlify,然后创建一个站点关联上github仓库。

在配置/部署里面添加构建命令

npm install -g reveal-md && reveal-md content/ --static --static-dirs=content/assets --template template/reveal.html --listing-template template/listing.html

然后在域名管理添加一个自己的域名

domain

配置成功如下

https://slides.onlythinking.com

参考

https://github.com/hakimel/reveal.js

https://github.com/webpro/reveal-md

https://revealjs.com/

https://app.netlify.com/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容