如何在没有 iframe 的页面中嵌入 PDF.JS 查看器

Posted

技术标签:

【中文标题】如何在没有 iframe 的页面中嵌入 PDF.JS 查看器【英文标题】:How to embed PDF.JS viewer in a page without iframe 【发布时间】:2020-10-30 03:00:03 【问题描述】:

我很惊讶地发现关于 PDF.JS 的文档和教程相对较少,尤其是在代码重构 PDFJS -> pdfjsLib 之后,考虑到这个库被广泛使用。

我想做的比较简单,我只想在网页中直接嵌入PDF,即没有<iframe><object><embed>标签。我还想使用文本层,因为我想在 javascript 中访问文本并在某些句子上添加工具提示。

我认为使用查看器可能是一种解决方案,但我不想在我的网页中包含 viewer.htmlviewer.cssviewer.js 中的所有代码,因为我确信它会损坏。如果我可以只显示 PDF 并选择文本就足够了,我不一定需要查看器的复杂用户界面。

这是我的代码,但文本层显示不正确:

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

function displayReport() 
  const file = document.getElementById('reportInput').files[0];
  const fileReader = new FileReader();
  fileReader.onload = async function() 
    const data = this.result;
    const pdf = await pdfjsLib.getDocument(data: data).promise;
    const page = await pdf.getPage(1);
    const viewport = page.getViewport(scale: 0.5);

    const canvas = document.getElementById('reportCanvas');
    const context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    const renderContext = 
      canvasContext: context,
      viewport: viewport
    ;
    await page.render(renderContext).promise;
    const textContent = await page.getTextContent();

    const  top, left, width, height  = canvas.getBoundingClientRect();
    const textLayer = document.getElementById('reportTextLayer');
    textLayer.style.top = top;
    textLayer.style.left = left;
    textLayer.style.width = width;
    textLayer.style.height = height;

    await pdfjsLib.renderTextLayer(
      textContent: textContent,
      container: textLayer,
      viewport: viewport,
      textDivs: []
    );

    console.log("Page rendered!");
  ;
  fileReader.readAsBinaryString(file);
#reportTextLayer 
  position: absolute;
  overflow: hidden;
  opacity: 0.2;
  line-height: 1.0;


#reportTextLayer > div 
  color: transparent;
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0% 0%;
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.js"></script>

<p>Select a PDF file:</p>
<input id="reportInput" type="file" accept="application/pdf" onchange="displayReport()"/>

<div id="reportWrapper">
    <canvas id="reportCanvas"></canvas>
    <div id="reportTextLayer"></div>
</div>

我该如何解决这个问题?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

这对我有用:

[script type="text/javascript" src="https://mozilla.github.io/pdf.js/build/pdf.js"][/script]
[script type="text/javascript" src="https://mozilla.github.io/pdf.js/build/pdf.worker.js"][/script]
[style type="text/css"]
#signature 
    margin-left:120px;
    margin-top:10px;

[/style]


    <canvas id='the-canvas'></canvas>
    <div id='signature'></div>

    [script]

    var url = "Agreement.pdf";
    var loadingTask = pdfjsLib.getDocument(url);
    loadingTask.promise.then(function(pdf) 
    pdf.getPage(1).then(function(page) 
    var scale = 1.5;
    var viewport = page.getViewport( scale: scale, );

    var canvas = document.getElementById('the-canvas');
    var context = canvas.getContext('2d');
    canvas.height = 640;
    canvas.width = viewport.width;

    var renderContext = 
    canvasContext: context,
    viewport: viewport
    ;
    page.render(renderContext);

    );    
    );

   document.getElementById('signature').innerHTML = 'Signed By Yogi on 1/26/2021'

   [/script]

【讨论】:

这可行,但非常简单,即:没有工具栏、滚动条、缩放等。从那以后你有改进吗?

以上是关于如何在没有 iframe 的页面中嵌入 PDF.JS 查看器的主要内容,如果未能解决你的问题,请参考以下文章

嵌入没有 iframe 的外部页面?

vue项目如何内嵌如iframe页面

如何同步iframe与嵌入内容的高度

iframe嵌入的子页面如何刷新父窗口

如何在一个html页面中嵌入多个iframe并实现table样式布局?

在一个页面中嵌入另一个页面使用iframe,但是被嵌入页面需要通过request传递参数应该如何实现?