居然可以用 js 寫 PPT?

用 powerpoint 或者 keynote 寫演示文稿,對於代碼、數學公式等的支持一直是個痛點。而且對於前端同學來說,一身的 css 功力用不上也是個痛點。對於使用 markdown 來寫文檔的同學來說,將文檔轉成 ppt 需要重新排版也是件重複性的工作量。

於是我們需要一個基於 web 技術的 ppt 框架,reveal.js 在這個領域成名已久了,而且上個月還有發佈新版本,維護得還蠻好,第一步我們就選它了。

將 reveal.js 運行起來

首先 clone 一份 reveal.js 最新的代碼:

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

我們照抄一份 index.html,比如叫做 study.html:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <meta >

  <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>

在 reveal.js 目錄下運行 npm install, 然後運行 npm start 就可以啓動一個 server 來查看上面的 ppt 網頁。默認使用 8000 端口,如果被佔用了可以通過指定 port 參數換一個,比如我們換成 30800 吧:

npm start -- --port=30800

然後通過訪問瀏覽器的 127.0.0.1:30800/study.html 就可以看到我們的 ppt 啦:

reveal.js step by step

上面這個網頁其實挺容易懂的,不用 react 或 vue 框架,也不需要配置 webpack。其核心內容部分其實非常簡單,就是每一頁演示文稿對應一個 section。

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

支持 markdown

reveal.js 的第一個強大功能是直接可以使用 markdown 來寫演示文稿。在我們上面默認的 html 模板中已經加載了 RevealMarkdown 插件。所以我們要做的就是在下面的模板上寫 markdown 就好。

<section data-markdown>
    <textarea data-markdown>                     
    </textarea>
</section>

我們來看個例子:

<section data-markdown>
    <textarea data-markdown>
推薦系統的主要算法包括:
- 矩陣分解
- 線性模型
- 樹模型
- 深度學習模型                        
    </textarea>
</section>

生成的幻燈片如下:

換個主題

如果覺得黑底白字的太醜了,我們可以換個主題。

主題就是個 css,在這條語句裏引用:

<link rel="stylesheet" href="dist/theme/black.css">

換成 dist/theme / 下面其它的 css 主題,或者乾脆自己擼一個。

比如改成:

<link rel="stylesheet" href="dist/theme/beige.css">

效果變成這樣:

支持數學公式

支持數學公式的 js 庫和插件默認並沒有包含在默認模板中,我們需要將其增加進來。

我們先把數學公式庫的 js 引進來:

<script src="plugin/math/math.js"></script>

然後在初始化時 Reveal.initialize 增加對於數學公式的配置, 並且引入 cdn 上的 mathjax 庫:

 Reveal.initialize({
        hash: true,
        math: {
          mathjax:
            "https://cdn.jsdelivr.net/gh/mathjax/mathjax@2.7.8/MathJax.js",
          config: "TeX-AMS_HTML-full",
          // pass other options into `MathJax.Hub.Config()`
          TeX: { Macros: { RR: "{\\bf R}" } },
        },

最後,在 plugins 中增加 RevealMath 插件:

        plugins: [RevealMarkdown, RevealHighlight, RevealNotes, RevealMath],      });

完整的代碼如下:

<script src="plugin/math/math.js"></script>
<script>
  Reveal.initialize({
    hash: true,
    math: {
      mathjax:
        "https://cdn.jsdelivr.net/gh/mathjax/mathjax@2.7.8/MathJax.js",
      config: "TeX-AMS_HTML-full",
      // pass other options into `MathJax.Hub.Config()`
      TeX: { Macros: { RR: "{\\bf R}" } },
    },

    plugins: [RevealMarkdown, RevealHighlight, RevealNotes, RevealMath],
  });
</script>

插件引入之後我們就可以在幻燈片中寫公式了。

可以直接在 section 中寫:

<section>
    \[\begin{aligned}
    MAE(X,h)=\frac{1}{m} \sum_{i=1}^m|h(x^i)-y^{(i)}| \
    \end{aligned} \]
</section>

也可以嵌入到 markdown 中:

 <section data-markdown>
  <textarea data-markdown>
                $MAE(X,h)=\frac{1}{m} \sum_{i=1}^m|h(x^i)-y^{(i)}|$                      
  </textarea>
</section>

出來的效果是這樣的:

代碼高亮

代碼高亮默認是支持的,我們可以在 markdown 裏面用 ``` 來使用:

顯示出來的效果如下:

md-code

也可以直接使用 html 的 pre 和 code 標籤來顯示:

<section>
    <pre>
        <code class="language-javascript">
            model.compile({
                optimizer: tf.train.sgd(0.000001),
                loss: 'meanSquaredError'
            });

            return model.fitDataset(flattenedDataset, {
                epochs: 10,
                callbacks: {
                    onEpochEnd: async (epoch, logs) ={
                        console.log(epoch + ':' + logs.loss);
                    }
                }
            });
        </code>
    </pre>
</section>

顯示的效果如下:

代碼高亮的 theme 也是可以更換的,只要更換 plugin/highlight 下面的 css 即可,例:

<link rel="stylesheet" href="plugin/highlight/zenburn.css" />

我們順便把 reveal.js 的 theme 也換一下:

<link rel="stylesheet" href="dist/theme/moon.css" />

效果變成下面這樣:

我們彙總下上面的代碼:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-sca
    />

    <title>reveal.js學習</title>

    <link rel="stylesheet" href="dist/reset.css" />
    <link rel="stylesheet" href="dist/reveal.css" />
    <link rel="stylesheet" href="dist/theme/moon.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>
            \[\begin{aligned}
            \ MAE(X,h)=\frac{1}{m} \sum_{i=1}^m|h(x^i)-y^{(i)}| \
            \end{aligned} \]
        </section>
        <section data-markdown>
          <textarea data-markdown>
推薦系統的主要算法包括:
- 矩陣分解
- 線性模型
- 樹模型
- 深度學習模型                        
                    </textarea
          >
        </section>
        <section data-markdown>
          <textarea data-markdown>
                        $MAE(X,h)=\frac{1}{m} \sum_{i=1}^m|h(x^i)-y^{(i)}|$                      
          </textarea>
        </section>
        <section>
            <pre>
                <code class="language-javascript">
                    model.compile({
                        optimizer: tf.train.sgd(0.000001),
                        loss: 'meanSquaredError'
                    });
                
                    return model.fitDataset(flattenedDataset, {
                        epochs: 10,
                        callbacks: {
                            onEpochEnd: async (epoch, logs) => {
                                console.log(epoch + ':' + logs.loss);
                            }
                        }
                    });
                </code>
            </pre>
        </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({
        hash: true,
        math: {
          mathjax:
            "https://cdn.jsdelivr.net/gh/mathjax/mathjax@2.7.8/MathJax.js",
          config: "TeX-AMS_HTML-full",
          // pass other options into `MathJax.Hub.Config()`
          TeX: { Macros: { RR: "{\\bf R}" } },
        },

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

背景圖片

section 支持 data-background-image 屬性來指定背景圖片。

例:

        <section data-background-image="https://cdn.jsdelivr.net/www.jsdelivr.com/000a3f2b6a7baa6ae0f786a251fd105e4b230d8e/img/landing/network-map@2x.png">        </section>

HTML and CSS

比起 markdown,HTML 和 CSS 也是寫演示文稿的好手段,可控的方法更多。而且也可以跟 reveal.js 的功能有更好的結合。

在 section 中,可以像在普通網頁中一樣寫 HTML 標籤:

<section>
    <h3 style="{color: #ffec3d;}">推薦系統的冷啓動</h3>
    <ul>
        <li>利用熱門數據</li>
        <li>利用用戶註冊信息</li>
        <li>利用第三方數據</li>
        <li>利用物品內容屬性</li>
    </ul>
</section>

我們也可以在 header 中寫 style 屬性給 section 中使用。

比如默認字體太大了,我們可以給調一調:

<style>
    ul {
        font-size: 18px;
    }
</style>

淡入淡出

結合 html 標籤,可以指定淡入淡出的效果。這可以通過給標籤添加 class 屬性爲 fragment 實現。

我們來看個淡入的例子:

<section>
    <h3>推薦系統的冷啓動</h3>
    <ul>
        <li class="fragment">利用熱門數據</li>
        <li class="fragment">利用用戶註冊信息</li>
        <li class="fragment">利用第三方數據</li>
        <li class="fragment">利用物品內容屬性</li>
    </ul>
</section>

除了淡入之外,我們還可以對某項進行標紅:

  <section>
      <h3>推薦系統的冷啓動</h3>
      <ul>
          <li class="fragment highlight-red">利用熱門數據</li>
          <li>利用用戶註冊信息</li>
          <li>利用第三方數據</li>
          <li>利用物品內容屬性</li>
      </ul>
  </section>

效果如下:

導出爲 pdf

演示文稿做好之後,除了在瀏覽器中看,我們也可以導出成爲 pdf 格式。方法是在 URI 之後增加 "?print-pdf" 後綴,比如:http://0.0.0.0:30800/study.html?print-pdf

然後我們再用另存爲 pdf 格式功能來保存下來就好。

更進一步

除了上面介紹的基本特性之外,reveal.js 支持自動播放、自制插件、支持處理事件等等有利於開發人員寫 slides 的特性。相信能給你的 slides 帶來新的好玩的東西,將彙報與分享變成樂趣。Enjoy it!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/JwnMZJC4ntUTPAO6Ty6jTg