创建可选内容图层(OCG)
将内容放入具名的可选内容组(OCG),通常称为图层。阅读器可以在其图层面板中切换各个图层,其中一个图层默认隐藏。本示例遵循 examples/26-layers.php。
OCG 是带有 Type /OCG 的 ISO 32000-2 可选内容组字典。NextPDF 会将分层标记包裹在 BDC/EMC 之间,并使用 OC 标记内容标签。
composer require nextpdf/core:^3不需要任何可选扩展。图层 API 自 1.0.0 起保持稳定,并可在 8.1–8.4 的向后兼容矩阵上运行。
概念总览
标题为“概念总览”的章节startLayer($name, $visible) 会打开一个 OCG。在配对的 endLayer() 之前绘制的所有内容,都属于该组。$name 是阅读器在图层面板中展示给用户的标签。ISO 32000-2 规定 OCG 的 Name 必须是面向用户的字符串。传入 $visible: false 会将该组以 OFF 状态注册到默认配置中,因此阅读器会隐藏它,直到用户手动打开。
可见性取决于阅读器是否配合。成员资格字典的默认可见性策略是 AnyOn,意思是只要任一被引用的组为 ON,该图层就会显示。被隐藏的图层只是按照阅读器惯例隐藏;它并未被移除或保护,既不是涂黑遮蔽,也不是安全控制机制。要移除内容,就不要绘制它。
API 接口
标题为“API 接口”的章节API 接口由 PHPDoc 自动生成。本示例会用到以下两个方法:
startLayer(string $name, bool $visible = true): static— 打开一个具名 OCG;$visible: false会让它默认隐藏。endLayer(): static— 关闭最近打开的图层(与startLayer()成对)。
代码示例 — 快速开始
标题为“代码示例 — 快速开始”的章节<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();
$doc->startLayer('Content', visible: true);$doc->setFont('helvetica', '', 12);$doc->cell(0, 8, 'Always-visible body content.', newLine: true);$doc->endLayer();
$doc->startLayer('Debug Grid', visible: false); // hidden until toggled$doc->setDrawColor(200, 200, 200);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}$doc->endLayer();
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf');代码示例 — 生产环境
标题为“代码示例 — 生产环境”的章节这是可以直接放入测试夹具运行的完整示例。它会遵循 NEXTPDF_COOKBOOK_OUTPUT,且不会固定自身产生的任何熵值。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Layer Examples (OCG)');$doc->addPage();
// Layer 1 — background, visible by default.$doc->startLayer('Background', visible: true);$doc->setFillColor(230, 240, 250);$doc->rect(10, 10, 190, 277, 'F');$doc->endLayer();
// Layer 2 — watermark, visible by default; can be toggled off.$doc->startLayer('Watermark', visible: true);$doc->setFont('helvetica', 'B', 54);$doc->setTextColor(200, 200, 200);$doc->startTransform();$doc->rotate(45, 105, 148);$doc->setXY(30, 135);$doc->cell(150, 20, 'DRAFT', align: Alignment::Center);$doc->stopTransform();$doc->endLayer();
// Layer 3 — main content, visible by default.$doc->startLayer('Content', visible: true);$doc->setTextColor(0);$doc->setFont('helvetica', 'B', 20);$doc->setXY(10, 15);$doc->cell(0, 14, 'Layer Examples (OCG)', newLine: true);$doc->ln(4);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'This document contains four optional content groups. ' . "Toggle them in your reader's Layers panel.");$doc->endLayer();
// Layer 4 — debug grid, hidden by default.$doc->startLayer('Debug Grid', visible: false);$doc->setDrawColor(180, 180, 180);$doc->setLineWidth(0.15);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}for ($y = 0.0; $y <= 297.0; $y += 10.0) { $doc->line(0, $y, 210, $y);}$doc->endLayer();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf';$doc->save($out);
echo "Created layers.pdf\n";边界情况与陷阱
标题为“边界情况与陷阱”的章节- 每个
startLayer()都要搭配一个endLayer()。 未关闭的图层会留下悬空的BDC,且没有对应的EMC,使文档结构变得不正确。请确保每次打开调用都有对应的关闭调用。 - 被隐藏的图层并未被移除。
visible: false只是按照阅读器惯例把内容隐藏起来。相关标记和文本仍然存在于文件中,而且可以恢复。这并不是涂黑遮蔽。对于敏感数据,请不要绘制它。 - 图层面板的支持程度各不相同。 要切换图层,需要使用支持公开可选内容控制的阅读器。打印管线与功能精简的查看器,可能始终显示或始终隐藏默认关闭的图层。
- 嵌套。 允许嵌套图层,但每个内层组的可见性仍然各自独立。除非你接入成员资格策略,否则不要假设外层关闭的图层会隐藏内层打开的组。
每个图层会新增一个 OCG 字典,外加一组围绕其标记的 BDC/EMC 配对。这点额外开销可以忽略不计。成本随图层内的内容增加,而不是随图层数量增加,因此这仍然远低于 2000 ms / 64 MB 的预算。
安全性说明
标题为“安全性说明”的章节可选内容的可见性**取决于阅读器是否配合,并非访问控制。**隐藏某个图层并不会加密、涂黑遮蔽或移除它的内容。任何人都可以重新启用该图层,或将相关字节提取出来。绝对不要用隐藏图层掩盖机密文字;应完全省略该内容。本示例不解析任何输入,也不访问网络。
符合性
标题为“符合性”的章节| 陈述 | 规范 | 条款 | 参考 ID |
|---|---|---|---|
OCG 字典带有 Type /OCG。 | ISO 32000-2 | §8.11.2 | |
OCG 的 Name 是必填、面向用户的标签。 | ISO 32000-2 | §8.11.2 | |
可选内容会包裹在 BDC/EMC 之间,并使用 OC 标签。 | ISO 32000-2 | §8.11.3.2 | |
| OCMD 策略有 AllOn/AnyOn/AnyOff/AllOff(默认为 AnyOn)。 | ISO 32000-2 | §8.11.4.3 |
可重现性配置文件 — 结构性。 尾部的 /ID 与日期原子值在每次保存时都会不同。测试夹具会剥离这些原子值,再比较经 qpdf 规范化后的结构。本示例说明 NextPDF 如何生成该结构。它不声明一般性的 ISO 32000-2 符合性。
商业情境
标题为“商业情境”的章节不适用。可选内容组是 Core 的能力,没有 Premium 的使用门槛。