给 PDF 加批注、按区域抽取数据、给图片套一圈边框,都要先知道目标元素落在页面的什么位置。PDF 内部并没有一张现成的坐标表:文字是一段段绘制指令,图片是页面资源里的对象,位置信息分散在各自的矩阵和矩形里。过去要么自己写解析器把这些数值拆出来,要么把文件传回服务端处理。
Spire.PDF for JavaScript 基于 WebAssembly 在浏览器端加载并解析 PDF 文档,通过虚拟文件系统(VFS)读写文件,不需要后端参与。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
坐标体系
使用 Spire.PDF 处理现有的 PDF 文档时,坐标的原点位于页面的左上角。X 轴从原点水平向右延伸,Y 轴从原点垂直向下延伸(如下图所示)。数值的单位是磅(1 磅 = 1/72 英寸),下面两个功能点里 Positions 与 Bounds 给出的都是这套口径下的数值。

获取指定文本的坐标
Spire.PDF for JavaScript 提供 PdfTextFinder,用于按内容查找文本在页面上的位置,每一处匹配都会给出落点坐标。查找以页为单位,多页文档需要逐页处理。
function App() {
const getTextCoordinates = 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);
// 取第 1 页
let page = doc.Pages.get_Item(0);
// 创建文本查找器,忽略大小写地搜索指定文本
let finder = new pdfModule.PdfTextFinder(page);
finder.Options.Parameter = pdfModule.TextFindParameter.IgnoreCase;
let results = finder.Find('玫瑰');
// 汇总每处匹配的坐标
let report = '';
for (let i = 0; i < results.length; i++) {
let find = results.get(i);
let position = find.Positions[0];
report += '第 ' + (i + 1) + ' 处匹配:' + find.Text + '\n';
report += ' 坐标:X = ' + position.X + ',Y = ' + position.Y + '\n';
}
// 将报告写入 VFS
const outputFileName = '文本坐标.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, new TextEncoder().encode(report));
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
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>获取文本坐标</h1>
<button onClick={getTextCoordinates}>
开始获取
</button>
</div>
);
}
export default App;
两处匹配各自的坐标

获取页面中图片的坐标
Spire.PDF for JavaScript 还提供 PdfImageHelper,用于读取页面中每张图片的位置。图片在页面资源里本来就有登记,取到的 Bounds 直接给出左上角坐标。同样按页取。
function App() {
const getImageCoordinates = 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);
// 取第 1 页
let page = doc.Pages.get_Item(0);
// 创建图片助手,取出该页的图片信息
let helper = new pdfModule.PdfImageHelper();
let images = helper.GetImagesInfo(page);
// 汇总每张图片的坐标
let report = '';
for (let i = 0; i < images.length; i++) {
let bounds = images[i].Bounds;
report += '第 ' + (i + 1) + ' 张图片:' + '\n';
report += ' 坐标:X = ' + bounds.X + ',Y = ' + bounds.Y + '\n';
}
// 将报告写入 VFS
const outputFileName = '图片坐标.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, new TextEncoder().encode(report));
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
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>获取图片坐标</h1>
<button onClick={getImageCoordinates}>
开始获取
</button>
</div>
);
}
export default App;
页面上三张花卉图片的坐标

常见问题
大小写不同就匹配不上
原因:Find() 的匹配行为由 Options.Parameter 决定,默认取值 TextFindParameter.None 按子串查找并区分大小写,Rose 与 rose 会被当成两回事。
解决:换成需要的取值即可,TextFindParameter 是标志枚举,能用按位或组合:
// 忽略大小写
finder.Options.Parameter = pdfModule.TextFindParameter.IgnoreCase;
// 只匹配整词,同时忽略大小写
finder.Options.Parameter = pdfModule.TextFindParameter.WholeWord | pdfModule.TextFindParameter.IgnoreCase;
// 用正则表达式查找:一次匹配 Rosa 或 Tulipa
finder.Options.Parameter = pdfModule.TextFindParameter.Regex;
let results = finder.Find('Rosa|Tulipa');
坐标数值和 PDF 阅读器里显示的对不上
原因:Positions 与 Bounds 用的是上面那套页面坐标系;而 PDF 文件内部(/MediaBox、内容流)用的是左下角原点、Y 轴向上,两套口径差着一个页面高度,直接对照就会差出整页的数值。
解决:统一按左上角原点处理,换算成像素时乘以 dpi / 72——96 dpi 下系数是 1.333。取到的数值本身就是浮点数,需要精确比对时保留两位小数再比较。
图片信息里没有页面上看到的那些图形
原因:GetImagesInfo 返回的是页面资源中的位图对象。用矢量指令画出来的线条、表格框和色块不属于图片;反过来,整页扫描件只有一张铺满页面的图片,图里的文字也搜不到。
解决:先用 Bounds 的 X、Y 确认每张图片实际落在页面的哪个位置。页面上用矢量指令画的线条与色块,GetImagesInfo 不会返回,扫描件里的文字也搜不到——这两类内容要定位,得走文本提取(PdfTextExtractor)或另行接入 OCR。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







