PDF 图层是把同一页上的内容划分到多个“可选内容组”(Optional Content Group,OCG)中的机制,最常见的应用如 CAD 图纸里的墙体、家具、电气分层,地图里的道路、水系、注记分层,以及需要在一页里按需切换的多种方案或多种语言内容。与直接把内容擦掉不同,图层可以让内容“既能藏起来、又能随时再打开”,在不破坏文档结构的前提下大幅提升同一份 PDF 的复用价值。
Spire.PDF for JavaScript 基于 WebAssembly 在浏览器端直接完成 PDF 的加载、绘制与保存,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
添加图层到 PDF
添加图层的过程是:先创建文档并添加页面,用 doc.Layers.AddLayer({ name, state }) 新建一个带名字的图层(state 可指定初始可见性),再调用该图层的 layer.CreateGraphics(page.Canvas) 拿到关联到该页画布的绘图上下文,之后便能用 DrawLine、DrawRectangle 等绘制方法把线条、色块等内容“画进”这个图层。下面的示例创建 red line、blue line、green line 三个图层,每个图层内各画一条对应颜色的横线与一个小色块,三条横线按不同高度错开排列。
function App() {
const addLayers = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 新建 PdfDocument 文档,并添加一页
let doc = new pdfModule.PdfDocument();
let page = doc.Pages.Add();
// 获取页面尺寸,用于在页面上相对定位
const width = page.Canvas.Size.Width;
const height = page.Canvas.Size.Height;
// 定义本地函数:把一条带同色小色块的横线绘制到指定名称的图层
const drawRow = (layerName, centerY, brush) => {
// 向文档添加一个图层,并设置其初始状态为可见
let layer = doc.Layers.AddLayer({ name: layerName, state: pdfModule.PdfVisibility.On });
// 获取该图层的绘图上下文
let g = layer.CreateGraphics(page.Canvas);
// 在图层内绘制一条彩色横线(横跨页面约 20%~80% 的宽度)
g.DrawLine({
pen: new pdfModule.PdfPen({ brush: brush, width: 2 }),
point1: new pdfModule.PointF(width * 0.2, centerY),
point2: new pdfModule.PointF(width * 0.8, centerY)
});
// 在横线左端绘制一个小色块,作为该图层颜色的标识
g.DrawRectangle({
brush: brush,
rectangle: new pdfModule.RectangleF({ x: width * 0.12, y: centerY - 6, width: 12, height: 12 })
});
};
// 三条横线自上而下排布,纵坐标分别取页面高度的 25%、50%、75%
drawRow('red line', height * 0.25, pdfModule.PdfBrushes.get_Red());
drawRow('blue line', height * 0.5, pdfModule.PdfBrushes.get_Blue());
drawRow('green line', height * 0.75, pdfModule.PdfBrushes.get_Green());
// 定义输出文件名并保存文档
const outputFileName = '添加图层.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Add Layers To PDF</h1>
<button onClick={addLayers}>
Generate
</button>
</div>
);
}
export default App;
添加 red line、blue line、green line 三个图层后的 PDF 页面

隐藏指定图层
当某些图层的内容暂时不想显示、但之后还需要再次打开时,不必删除它们,只需把对应图层的 Visibility 属性设为 PdfVisibility.Off 即可“隐藏”。隐藏后内容不再显示,但图层与其中的对象仍保留在 PDF 里,阅读者可以在 PDF 查看器的图层面板中随时重新开启。下面的示例载入一份官方分层 PDF 样例(其中已含 red line、blue line、green line 三个图层),用 get_Item({ name }) 按名称获取其中两个图层并把它们的 Visibility 设为不可见,页面上便只保留 green line 图层的内容。
function App() {
const hideLayers = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将含多个图层的 PDF 样例载入 VFS
const inputFileName = '添加图层.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 按名称获取“red line”与“blue line”图层,并设为不可见,页面上仅保留“green line”
doc.Layers.get_Item({ name: 'red line' }).Visibility = pdfModule.PdfVisibility.Off;
doc.Layers.get_Item({ name: 'blue line' }).Visibility = pdfModule.PdfVisibility.Off;
// 定义输出文件名并保存文档
const outputFileName = '隐藏图层.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Hide Layers In PDF</h1>
<button onClick={hideLayers}>
Generate
</button>
</div>
);
}
export default App;
隐藏 red line 与 blue line 图层后,页面仅保留 green line 图层内容

删除图层
当某个图层及其内容不再需要时,可以用 doc.Layers.RemoveLayer 把它从文档的图层集合中删除:传入图层名称即可,例如 RemoveLayer({ name: 'red line' }) 会把名为 red line 的图层整个移除,之后该图层中的内容不再显示,也不能再通过图层面板恢复。
function App() {
const deleteLayer = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将含多个图层的 PDF 样例载入 VFS
const inputFileName = '添加图层.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 按名称删除“red line”图层,页面将不再显示该图层内容
doc.Layers.RemoveLayer({ name: 'red line' });
// 定义输出文件名并保存文档
const outputFileName = '删除图层.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Delete PDF Layer</h1>
<button onClick={deleteLayer}>
Generate
</button>
</div>
);
}
export default App;
删除 red line 图层后,页面仅保留 blue line 与 green line 图层

常见问题
隐藏图层和删除图层有什么区别
原因:隐藏与删除都会让内容在页面上“看不见”,容易混淆两者在文档结构上的差别。
解决:隐藏是把图层 Visibility 设为 Off,图层与其中的对象仍保留在 PDF 里,之后用查看器的图层面板可随时再开启;删除则通过 RemoveLayer 把图层从 doc.Layers 中整个移除,其内容不再显示、也无法恢复。简单说:暂时不看用隐藏,永远不要用删除:
// 隐藏:内容仍在文档中,可随时再开启
doc.Layers.get_Item({ name: 'red line' }).Visibility = pdfModule.PdfVisibility.Off;
// 删除:从图层集合中移除,无法再开启
doc.Layers.RemoveLayer({ name: 'red line' });
添加图层时如何控制图层初始是否可见
原因:AddLayer 新建的图层默认可见,而有些图层希望一开始就处于隐藏状态(例如预置但暂不展示的备用方案)。
解决:AddLayer 的 state 参数可指定图层的初始可见性,传 PdfVisibility.Off 即创建为不可见,传 On(或省略)则创建后立即可见。创建后再用 Visibility 属性随时切换:
// 新建一个初始即不可见的图层
doc.Layers.AddLayer({ name: '备选方案', state: pdfModule.PdfVisibility.Off });
如何按名称或索引定位图层
原因:对含多个图层的文档,常需要操作某个特定图层,而 Layers 集合里有多个元素,需要准确的定位方式。
解决:doc.Layers 是图层集合,Count 给出图层总数,get_Item({ name }) 按图层名取值,get_Item(i) 按下标取值。需要批量控制时遍历所有图层即可,例如把所有图层一并设为不可见:
// 遍历图层集合,把所有图层设为不可见
for (let i = 0; i < doc.Layers.Count; i++) {
doc.Layers.get_Item(i).Visibility = pdfModule.PdfVisibility.Off;
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







