跳到主要内容

章 12.2 · 篇 III · 实践

沙盒:预览

主视口中的Canvas、PDF、书页、HTML和EPUB 3标签页:各自显示什么,能做什么

更新于 2026-10-1610分钟所属章节: 12 沙盒enescadefritptzhjaar

简单来说

本页介绍沙盒右侧显示排好页面的区域。五个标签页用五种方式显示同一本书:页面图像、PDF文件、可以翻阅的3D书、网页和EPUB电子书。切换标签页不会重新排版,所以每个标签页显示的都是同样的页面。本页说明每个标签页显示什么,以及你在其中能做什么。

#主视口

界面的右侧显示渲染结果。共有五个标签页,每种渲染模式一个,依次为Canvas、PDF、书页、HTML和EPUB 3。切换标签页不会重新排版:同一个VDT供给所有后端,所以你在不同模式中看到的内容是一致的。只有浏览器支持WebGL2、且屏幕不是手机屏幕时,才提供书页标签页(见书页标签页)。

每个视口都在一个专用的Web Worker(postext/worker)中运行排版流程。每个视口的useLayoutWorker hook持有工作线程的句柄,以可转移的ArrayBuffer把字体送入工作线程,并以后发优先的取消机制驱动构建——每次按键或拖动滑块时,都会先通过AbortSignal中止前一次构建,再开始下一次,所以快速输入永远不会在主线程上堆积过时的工作。卸载视口时,会销毁它的工作线程,并拒绝所有未完成的构建。这里使用的集成方式见配置 → 在Web Worker中运行排版。

一个VDT,五种输出沙盒中的Markdown和配置供给内存中唯一的一个VDT。Canvas、PDF、书页、HTML和EPUB 3都从同一个VDT渲染,所以每个标签页显示的都是同一个版面。Markdown配置VDT共享的版面唯一的数据来源CanvasPDF书页HTMLEPUB 3
同一个VDT供给五个输出标签页。

#Canvas标签页

在HTML5的<canvas>元素上渲染文档的栅格化预览。它以像素级的精度呈现最终排好的文档的样子,包括文字的精确位置、栏式和资源的安放位置。

Canvas视口顶部的工具栏提供:

  • 缩放控件——放大和缩小(每级1.25倍,范围0.25x–4x)。手动缩放会关闭适应模式。
  • 适应模式——适应页面宽度或适应页面高度。可以开关;窗口大小改变时会自动重新计算。
  • 视图模式——单页(每行一页)或双页跨页(仿照书本的布局:第一页作为右页单独出现在右侧,之后的页面两两组成跨页)。右侧装订的书(page.binding,竖排中文)以相反的方向显示跨页:第1页单独在左边,然后是[3 | 2]、[5 | 4]。在竖排页面上,点击会落在指针下方的字符上,光标是一条横贯该栏的短横。
  • 印刷预览(Printer图标)——按印出来的样子显示页面,默认关闭,浏览器会记住这个选择:每种颜色都经印前准备中的输出特性文件分色,显示在纸张自身的白色上;大面积黑色显示为复合黑;强制为灰度的PDF只以黑墨显示。只显示会印出来的内容:不画屏幕参考线,也不画红框(印前检查发现的问题见检查)。书页标签页共用这个开关。它只重绘页面,从不重新排版。

页面通过IntersectionObserver延迟渲染——只有可见的页面(外加200px的余量)才会绘制到画布上,这样长文档也只占用很少的GPU内存。

#PDF标签页

通过postext-pdf软件包生成当前文档的真正PDF,并在内嵌的浏览器PDF查看器中显示。PDF在首次挂载时以及之后每次重新生成时自动重建,所用的是供给Canvas和HTML标签页的同一个VDT——所以三个后端的断行、分页和资源位置逐像素一致,连Knuth–Plass偶尔接受的超长末行的压缩都相同。

视口右下角的浮动工具栏提供:

  • 重新计算(RefreshCw图标)——根据当前的Markdown和配置重建PDF。在改动了不会自动触发重建的设置之后,或字体加载完成之后,可以用它。
  • 下载(Download图标)——把当前PDF保存到磁盘。文件名取自文档的第一个H1标题(没有时为document.pdf)。
  • 打印(Printer图标)——针对内嵌的PDF查看器打开浏览器的打印对话框,大多数浏览器在这里既可以打印,也可以再次另存为PDF。
  • 当前章 / 整本书(标签栏左侧的选择器,只在多于一章的书中出现)——把所有章渲染为一个连续的PDF,而不是默认的当前章(接续其前各章)。更改它会重新生成PDF。Canvas有自己的选择器(见书与章)。

在底层,沙盒使用一个createPdfFontProvider()辅助函数:它从Fontsource的jsdelivr CDN获取按字重区分的静态WOFF2文件(也就是预览测量时所用的文件),在浏览器中解压为TTF,再通过renderToPdf把字节交给pdf-lib。之所以需要按字重区分的静态字体(而不是一个可变字体),是为了让粗体文字真正以粗体字重嵌入。在沙盒之外使用同样做法的方式,见生成PDF。

#书页标签页

把书作为印刷品来展示:引擎排好的页面装订成书,摊开放在桌面上,以3D呈现(postext-folio,three.js)。页面就是Canvas绘制的结果,逐像素显示,所以文字和Canvas标签页上一样清晰;变化的是页面周围的一切。纸张、装订、桌面和光照来自版面设计面板中的Folio组(即folio配置);正文中的:::paper段落会把其中的页面印在另一种纸上(见文档格式 › :::paper)。

  • 排出的内容。 书页标签页跟随Canvas的当前章 / 整本书选择器。一章显示为它所在的书的一部分:它前后的页面计入两侧书芯的厚度,这一章在跨页中也从它真正所在的一侧打开。右侧装订的书(page.binding: 'right',或竖排的书)呈镜像,向左翻页。
  • 翻页。 抓住页边拖过去:过了一半松手就翻过去,不到一半就落回原处。点击页面也会翻页(右页向前,左页向后);工具栏的‹ ›按钮,以及书本获得焦点时的方向键、Page Up/Down、Home和End,也都可以翻页。每一叶按自己的纸张弯曲:字典纸卷得很紧,卡纸翻出宽大的弧线,纸板和封面则像硬板一样整块翻动。
  • 远距离跳转。 相距超过十页的页面(在页码框中输入、由永久链接指定、通过链接或文本面板中的光标到达)一次到位:中间的整叠书页作为一个整体掀起,厚度与这些页相同,再落到另一侧。十页以内则逐页翻过。
  • 绕着书看。 按住右键拖动可让视角绕书旋转,最低到偏离正上方70°,用来查看书脊、切口或书芯的厚度。视角停在你放开的位置,翻页时也不变,直到重置视角把它平缓地恢复到设置给出的视角(倾斜角和转角)。保存为默认视角把你当前看到的视角存入这两项设置,书会以这个视角打开,重置视角也会回到这里。
  • 指针的作用。 工具栏的三个按钮决定左键(一根手指、一支笔)在书上的作用:用手翻页为默认模式,如上所述;环绕视角与右键拖动相同,适合触控板或平板;选择文本的用法与Canvas标签页相同,作用于眼前所见的书,无论倾斜还是旋转:单击把光标放到文本面板,拖动进行选择,双击选中一个词,单击链接则跟随链接。选择会被记住;书获得焦点时,按H、O、S可切换。
  • 跟随编辑器。 文本面板的光标和选区画在书页上,输入时也保留:页面重新排版后立即显示修改。在编辑器中把光标移到未显示的页面,书会翻到那一页。
  • 封面。 选择封面:书页外加书壳时,书用布面、卡纸或皮面的书壳装订,颜色为封面颜色。选择文档自带的页面时,第一页是封面,最后一页(落在左页时)是封底:翻开封面之前书是合着的,翻过最后一叶时书又合上。厚书打开时,书脊立在两侧书芯之间。
  • 工具栏。 与Canvas相同的浮动工具栏:重新计算、重置视角、保存为默认视角、三种指针模式、印刷预览(与Canvas相同的打样,显示在输出特性文件的纸白上,因此期间不使用书本纸张的色调;与Canvas的开关相同)、固定按钮、‹ ›和页码框;页码框接受书中的页码,并翻到它所在的跨页。打开的跨页中右侧那一页就是永久链接所标明的页(view=folio&page=N)。
  • 设置即时生效。 书页设置不属于排版:改变纸张、装订或光照只会重绘书本,不会重新排任何一页。
  • 在哪里提供。 这个标签页需要WebGL2,以及短边至少600像素的屏幕:在手机上,3D书本占用的内存超过浏览器给一个标签页的上限,所以那里不显示这个标签页(不支持WebGL2的浏览器也不显示)。窗格宽度小于560像素时,书一次显示一页,书页仍绕着书脊翻动。系统要求减少动画时,跨页直接切换,不播放翻页动画。
  • 页面上的视频。 在三种指针模式中的任何一种下,点击视频的封面,它就在页面上播放,翻动这一叶时画面随纸张弯曲卷起,仍在播放。再点击一次暂停;开始播放另一个视频时,前一个会停止,除非打开了与其他视频同时播放;书停在不再显示这个视频的跨页上时,它也会停止。空格键播放或暂停打开的跨页上的视频。打开了自动播放的视频在它的跨页第一次出现时自动开始播放;你在页面上点击过之后它才有声音(在此之前静音,点击一次打开声音),指南中的两个视频就是这样设置的。上传的文件和位于某个地址的视频(MP4、HLS)只要服务器允许跨源读取,都能这样播放;YouTube和Vimeo视频照旧翻页(见文档格式 › Folio视图中的视频)。
  • 替代文本。 每一页都以图像绘制;它的无障碍名称会指引读者到HTML标签页和正文面板查看文字。

#HTML标签页

在Shadow DOM容器中渲染postext的输出,使其样式与宿主页面完全隔离。版式CSS(字体排印、间距、栏线)注入在shadow root内部,因此既不会受到周围应用样式的影响,也不会泄漏到其中。

Markdown链接在这里和PDF中都是可点击的(见文档格式 › 链接)。在这个标签页中,点击链接会在新的浏览器标签页中打开目标,沙盒保持打开;:ref引用仍在文档内部跳转。

视频在这里播放:YouTube或Vimeo视频用平台的播放器,文件或网址用浏览器的播放器(浏览器本身不能播放HLS时,HLS流通过hls.js播放),播放器选项取自设计面板的视频样式和各个视频的设置。在播放器上的点击交给播放器,不会跳到编辑器。HTML 查看器中设为封面时,这个标签页显示印刷封面,并链接到视频。

视口顶部的工具栏提供:

  • 字号缩放控件——缩小或放大正文,同时保持配置中所有相对尺寸的比例。
  • 分栏模式——单栏(一个可以滚动的长栏)或多栏(栏宽最接近所配置行长的栏数,页面之间水平滚动并自动吸附)。双栏文档保持双栏页面,但阅读器可能显示奇数个栏——比如三栏,而不是拉宽的两栏或挤窄的四栏——如果那样最接近;这时最后一栏属于下一页,只露出一半。多栏版式的文档或章节也显示为双栏页面:三到八栏的印刷栏放到屏幕宽度上会窄成细条,所以阅读器把它的文字排成每页两栏,并按行长并排显示尽可能多的栏。右侧装订的书(page.binding)在多栏模式下从右到左排列页面:阅读器从最右端开始,‹箭头转到下一页。竖排的书只能以多栏模式阅读:单栏按钮不可用,悬停提示会说明原因;你保存的选择会在下一本横排的书中恢复。

栏的几何尺寸由版面设计面板中的网页阅读器(HTML)分区(版面设计 → 导出)决定:maxCharsPerLine以正文字体的字符数设置目标行长,columnGap设置多栏模式下栏与栏之间的水平间距,optimalLineBreaking在阅读器中开关Knuth–Plass算法。沙盒内部采用的同样做法见HTML阅读器配置参考和端到端的集成示例。

#EPUB 3标签页

用postext-epub包把整本书写成一个EPUB 3文件,在标签页内的阅读器中显示,并可下载。文件在浏览器中生成,所用的逐章排版与PDF标签页选整本书时相同,因此页码、注释、交叉引用、目录和索引都与PDF印出的一致。这个标签页没有当前章/整本书选择器,因为EPUB总是包含整本书。在标签栏左侧的那个位置,它提供EPUB的版式选择(手机上显示为图标)。

EPUB 3有两种版式,由包文件的rendition:layout属性声明:

  • 固定版式(pre-paginated,英文称fixed layout或FXL):每一页都保持印刷时的样子。每页是一个独立的文档,尺寸与页面相同,文字的位置与PDF一致,使用书中的字体,但仍是真正的文字,可以选择、搜索和朗读。跨页按印刷本配对,右装订的书(阿拉伯文、竖排中文)从右向左翻页。它保留版面设计:分栏、浮动体、书眉、章首页和确切的断行。适合页面本身就是设计对象的书,如图文书、教材、目录册和杂志,也适合大屏幕的阅读器。在小屏幕上页面会缩小显示,读者需要放大阅读。
  • 流式版式(手机和电脑上的默认版式,也是EPUB的默认版式;英文称reflowable):正文、图和表按阅读顺序排列,由阅读器按自己的屏幕以及读者所选的字体、字号和边距重新排版。段落由排好的行重新拼合(行末添加的连字符会去掉),图和表跟在引用它们的文字之后,标注框成为旁注(aside),脚注链接到每章末尾的注释并可返回,印刷页码保留为分页标记。从版面设计导出的样式表决定标题、标注框、表格和图注的外观,但页面几何不复存在:没有分栏,没有书眉,没有固定的断行。适合连续的正文,如小说、随笔和报告,也适合手机和电子墨水阅读器。

在没有选择之前,这个标签页在iPad这样的平板电脑上以固定版式打开,因为它的屏幕放得下印刷页,在其他设备上则以流式版式打开。这个选择在下次访问时仍然保留(postext-sandbox-epub-layout),切换后文件会立即重新生成。

  • 生成。 第一次打开标签页时生成EPUB,按重新计算时再次生成。进度条先统计正在排版的章,再显示写入的各个步骤(字体、图片和封面;页面或章;打包),文件生成完毕或失败时屏幕阅读器会播报。编辑之后,重新计算旁边会出现一个箭头,表示文件已与文本不符,与PDF标签页相同。离开标签页或切换版式会中止正在进行的生成。长书需要几秒钟,其间页面不响应操作。
  • 文件包含什么。 元数据取自第一章的前置元数据:title、subtitle、author(一个名字或一个列表)、publishDate或date、isbn或identifier、publisher、rights和description;语言取自配置中的locale。没有标识符的书会得到一个由项目(或由示例书及其语言)派生的标识符,这样同一本书的所有EPUB在读者的书库中保持同一身份。版面设计中提到的所有字体族都会嵌入:Google Fonts只收入书中实际用到的字符所在的分片;自定义字体族也会收入,标记为不可再分发的除外。图片按存储时的样子收入,从不使用PDF印刷母版;每个SVG都带有其文字指定的字体(自定义字体族和Google字体族一样),标记为不可再分发的字体族除外,这些会被报告。视频文件收入media/下,在阅读器的播放器中播放;没有文件字节的视频从其正式发布地址播放,包文件把它声明为远程资源;YouTube或Vimeo视频则显示为链接到视频的封面。封面是书自带的图片(须为至少600像素宽的位图);否则就把第一页按1600像素宽绘制,并去掉裁切标记的边距。
  • 阅读器。 标签页打开的就是刚写好的文件,与下载的字节完全相同,而不是另做的预览。固定版式显示一页,窗格足够宽时显示一个跨页,并缩放到合适大小;流式版式的书按屏幕分页(竖排中文从上到下),页面从一章接续到下一章。书中的链接在阅读器内跳转;网页和邮件链接在浏览器的新标签页中打开。←/→、Page Up/Page Down、Home和End用于翻页,从右向左的书中←是向前翻。
  • 工具栏。 与PDF标签页相同的浮动工具栏:重新计算、固定按钮、显示文件大小的下载 EPUB(文件以书名命名)、写入时有提醒才出现的提醒按钮、目录(根据书的目录生成的跳转列表)、增大字号和减小字号(仅流式版式,阅读位置保持不变)、‹ ›,以及固定版式下的页码框。页码框按文件的阅读顺序计页,封面算第1页;各页框架的名称使用印刷页码。
  • 提醒。 提醒按钮列出文件未能按书中原样收入的内容:没有存储文件的图片(原处留下空框)、没有嵌入字形的字体族、字重或字形(阅读器会替换)、因不可再分发而未收入的字体族,以及该版式无法表达的内容。同样的消息也会输出到浏览器控制台。
  • 检查文件。 指南和示例书的两种版式都能通过W3C EPUBCheck 5.4检查,没有错误或警告。要检查自己的书,下载后运行epubcheck book.epub,或者在Apple Books、Thorium Reader或Calibre中阅读。

要在自己的代码中写出同样的文件,见EPUB电子书。