You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无iframe页面嵌入PDF.JS并修复文本层显示异常

Fixing PDF.js Text Layer Display Issues (Without Full Viewer)

我完全懂你的感受——PDF.js重构到pdfjsLib之后,轻量场景的文档确实不够完善,明明是应用这么广的库,想不依赖臃肿的viewer实现基础PDF显示+文本层功能,踩坑是真的闹心。你的文本层显示异常主要是几个细节没处理到位,咱们一步步来修复:

核心问题分析

你的代码里有几个关键问题导致文本层错位或无法正常显示:

  1. 定位单位缺失:给top/left/width/height赋值时没加px单位,浏览器无法正确解析样式
  2. 文件读取方式过时:readAsBinaryString已经被废弃,用arrayBuffer更稳定且符合PDF.js官方推荐
  3. 缩放未同步:canvas用了scale:0.5,但文本层的缩放逻辑没跟上,导致错位
  4. 冗余参数干扰:手动传入textDivs: []反而会影响文本层的自动生成逻辑

完整修复代码

HTML

<p>Select a PDF file:</p>
<input id="reportInput" type="file" accept="application/pdf" onchange="displayReport()"/>
<!-- 给容器加相对定位,确保文本层定位基准正确 -->
<div id="reportWrapper" style="position: relative;">
  <canvas id="reportCanvas"></canvas>
  <div id="reportTextLayer"></div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.js"></script>

CSS

#reportWrapper {
  position: relative;
  /* 可选:限制容器宽度,避免PDF过宽撑爆页面 */
  max-width: 800px;
}

#reportTextLayer {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  opacity: 0.2;
  line-height: 1.0;
  /* 和canvas保持一致的缩放比例,确保对齐 */
  transform: scale(0.5);
  transform-origin: top left;
}

#reportTextLayer > div {
  color: transparent;
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0% 0%;
  /* 调试时可以打开这个背景色,方便查看文本层位置,完成后可删除 */
  /* background: rgba(255, 0, 0, 0.1); */
}

JavaScript

document.addEventListener('DOMContentLoaded', () => {
  pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.worker.js';
});

async function displayReport() {
  const file = document.getElementById('reportInput').files[0];
  if (!file) return;

  // 改用arrayBuffer读取文件,替代已废弃的readAsBinaryString
  const arrayBuffer = await file.arrayBuffer();
  const pdf = await pdfjsLib.getDocument({data: arrayBuffer}).promise;
  const page = await pdf.getPage(1);
  
  const scale = 0.5;
  const viewport = page.getViewport({scale});
  
  const canvas = document.getElementById('reportCanvas');
  const context = canvas.getContext('2d');
  canvas.height = viewport.height;
  canvas.width = viewport.width;
  
  const renderContext = { canvasContext: context, viewport };
  await page.render(renderContext).promise;
  
  const textContent = await page.getTextContent();
  const textLayer = document.getElementById('reportTextLayer');
  
  // 每次渲染前清空文本层,避免多次上传PDF时文本叠加
  textLayer.innerHTML = '';
  
  // 移除冗余的textDivs参数,让函数自动生成文本元素
  await pdfjsLib.renderTextLayer({
    textContent,
    container: textLayer,
    viewport
  });
  
  console.log("Page rendered with functional text layer!");
}

关键修改说明

  1. 定位基准优化:给reportWrapper添加position: relative,让文本层相对于容器定位,不会因为页面滚动而错位
  2. 缩放同步处理:文本层直接通过transform: scale(0.5)和canvas保持一致的缩放比例,比动态计算getBoundingClientRect更稳定
  3. 文件读取升级:用arrayBuffer替代废弃的readAsBinaryString,这是PDF.js官方推荐的文件读取方式
  4. 冗余参数清理:移除textDivs: [],让renderTextLayer自动生成文本div元素,避免干扰默认逻辑
  5. 文本层重置:每次渲染前清空文本层内容,防止多次上传PDF时文本叠加

修改完成后,文本层就能和canvas完美对齐,你可以正常选中文本,后续也能轻松给指定文本添加tooltip——只需要遍历textContent里的字符块,找到对应文本的div元素绑定事件即可。

内容的提问来源于stack exchange,提问作者JacopoStanchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:42:45