我不记得我何时或如何第一次遇到 CSS Scroll Snap 技术,但是当我看到它时,我立即想到了一件事:我们可以使用这种技术来制作幻灯片吗? (剧透:后来的答案是“是” )
如果您之前没有听说过,这里有 MDN 上的快速介绍,可以帮助您入门。基本上,它使元素在您滚动到元素上时可以“捕捉”,这意味着一旦您滚动到某个元素上,它就会快速跳到您的视图中,而不是等待您不断地滚动它。如果您使用过移动设备查看照片,您应该熟悉这种用户体验。
幻灯片给了我们类似的体验。如果我们有一个包含多个部分的 HTML 页面,我们可以使用这种 CSS 技术使每个部分“对齐”。那么这个连续的页面就变成了一系列的“幻灯片”!
三个 CSS 属性
一个只有三个 CSS 属性的新 HTML5 演示框架?听起来棒极了。没有人可以阻止我继续努力。
html { scroll-snap-type: y mandatory; } .slide { min-height: 100vh; /* occupy at least 100% viewport height */ scroll-snap-align: start; }
我最终将这 7 行 CSS 扩展为约 100 行 ( snap.css ),以设置幻灯片的其他几个常见元素的样式,例如目录、幻灯片标题、页码、计时器和特殊页面。
通过 JS 将内容组织为幻灯片页面
如果 HTML 代码组织良好,由一系列部分组成(例如<div class="slide">
),我可能不需要编写太多 JavaScript。最终我写了大约 140 行 JS ( snap.js )。三分之一的代码将内容重新组织到幻灯片页面中,例如,转换
<h2>First slide</h2> <p>Content</p> <hr> <h2>Second slide</h2> <p>More content</p> <hr>
到
<div class="slide-container"> <div class="slide"> <h2>First slide</h2> <p>Content</p> </div> <div class="slide"> <h2>Second slide</h2> <p>More content</p> </div> </div>
基本假设是您使用水平线 ( <hr>
) 来分隔幻灯片,或者每个二级部分 ( <h2>
) 都是一张幻灯片。
其余的 JS 代码处理脚注、页码、计时器、幻灯片属性和键盘快捷键。
将 JS 和 CSS 放在一起
如果你幸运的话(或者我在编写 JS 代码时足够聪明),你可以在将 JS 和 CSS 添加到页面后将你的 HTML 页面变成幻灯片:
<script src="https://cdn.jsdelivr.net/gh/rstudio/[email protected]/inst/resources/snap.min.js" defer></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/gh/rstudio/[email protected]/inst/resources/default.min.css,gh/rstudio/[email protected]/inst/resources/snap.min.css">
我用的是1.8以上的版本。你可以在这里查看其他版本的 Git 标签(最小是 1.6)。
当然,你更愿意用 Markdown 而不是 HTML 来编写幻灯片
您可能对上面的所有 HTML/JS/CSS 代码和术语感到皱眉。好消息是您可以忘记它们,然后单击按钮即可从 Markdown 生成幻灯片。下面我将介绍两种方法。
使用markdown包
您可以安装markdown包(不是r markdown)。然后使用 YAML 元数据创建一个.md
文件(如果需要使用knitr代码块,则创建.Rmd
):
--- title: "Snap Slides" output: markdown::html_format: meta: css: [default, slides] js: [slides] ---
对于正文,在两张幻灯片之间插入一条水平线,如下所示:
## First slide **Content**. --- More _content_ on the next page. --- ## Third slide
如果您在 RStudio 中编辑文件,请单击Knit
按钮以生成幻灯片。如果不这样做,您可以在.md
文件上调用markdown::mark_html()
,或在.Rmd
文件上rmarkdown::render()
。
使用四开
JS/CSS 代码不绑定到markdown包(尽管代码托管在此包中)。您绝对可以在四开本文档中使用它。关键是设置选项minimal: true
并通过include-after-body
包含JS/CSS:
--- title: "Snap Slides" format: html: minimal: true include-after-body: text: | <script src="https://cdn.jsdelivr.net/gh/rstudio/[email protected]/inst/resources/snap.min.js" defer></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/gh/rstudio/[email protected]/inst/resources/default.min.css,gh/rstudio/[email protected]/inst/resources/snap.min.css> <style type="text/css">header{text-align: center;}</style> ---
如果您不喜欢从网络(jsdelivr CDN)加载 JS/CSS,您可以在本地下载副本并包含本地副本,这将确保您的幻灯片可以离线工作。
我喜欢它的原因
2017 年,我写了一篇关于为什么我喜欢 remark.js 幻灯片的文章。 2与 remark.js 相比,我喜欢的大部分功能都在 snap.js 中。缺失的包括:
- 增量幻灯片。
- 主持人笔记。
- 突出显示特定的代码行。
他们都不打扰我。我对实现 #2 很感兴趣,并且对如何实现有一个模糊的想法(克隆窗口并使用Intersection Observer
来同步两个窗口)。除此之外,snap.js 对我来说功能很完整。
与 remark.js/ xaringan相比,使用 snap.js 的一大优势是我们可以使用 RStudio Visual Markdown 编辑器(或任何支持 Pandoc / CommonMark 的可视化编辑器)。
这种幻灯片格式的一个可能的独特特征是一张幻灯片可以任意长,在这种情况下滚动行为将变得正常(即连续)。如果您的内容无法容纳一张幻灯片,请不用担心。
按扣幻灯片框架非常轻巧。这使得开源黑客在对任何内容不满意时调整其源代码是理想的选择,尽管我认为这应该是最后的手段——您已经可以在不触及源代码的情况下自定义许多东西。再次想要yolo = TRUE
Karl Broman 吗?没问题(我将把这个练习留给你)。
到目前为止,我只被一个小问题困扰:无论我使用鼠标还是箭头键,我都无法快速滚动幻灯片,而且我对此无能为力(限制来自系统)。我可以通过按Home
键(或Cmd + Up
)跳转到第一张幻灯片,通过End
( Cmd + Down
)跳转到最后一张幻灯片。对于其余幻灯片,只有在当前幻灯片停止捕捉(这需要很短的时间)后,您才能滚动到下一张幻灯片。不过,幻灯片的概述模式可以提供一些帮助。
演示和文档
markdown包中的vignette('slides', package = 'markdown')
可以作为该幻灯片框架的演示和文档。享受!