使用PDF.js将链接、超链接插入画布

13

我正在使用PDF.js库将PDF渲染到画布中,该PDF中有超链接。PDF.js库将PDF绘制到画布上,但超链接无法工作。

有什么方法可以使超链接在画布中工作吗?

谢谢

3个回答

19

这里是一个JSFiddle示例,可演示如何在PDF文件中启用批注(包括超链接)。 此示例使用的原始PDF文件在此处

我参考了查看器代码(web/page_view.js,web/viewer.css)来编写这个JSFiddle。

HTML:

<!doctype html>
<html lang="en">
  <head>
    <link href="style.css" rel="stylesheet" media="screen" />
    <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script src="http://seikichi.github.io/tmp/PDFJS.0.8.715/pdf.min.js" type="text/javascript"></script>
    <script src="http://seikichi.github.io/tmp/PDFJS.0.8.715/ui_utils.js"></script>
    <script src="./main.js" type="text/javascript"></script>
  </head>
  <body>
    <div id="pdfContainer" class="pdf-content">
      <canvas id="the-canvas"></canvas>
      <div class="annotationLayer"></div>
    </div>
  </body>
</html>

CSS:

->

CSS:

body {
    font-family: arial, verdana, sans-serif;
}
.pdf-content {
    border: 1px solid #000000;
}
.annotationLayer > a {
    display: block;
    position: absolute;
}
.annotationLayer > a:hover {
    opacity: 0.2;
    background: #ff0;
    box-shadow: 0px 2px 10px #ff0;
}
.annotText > div {
    z-index: 200;
    position: absolute;
    padding: 0.6em;
    max-width: 20em;
    background-color: #FFFF99;
    box-shadow: 0px 2px 10px #333;
    border-radius: 7px;
}
.annotText > img {
    position: absolute;
    opacity: 0.6;
}
.annotText > img:hover {
    opacity: 1;
}
.annotText > div > h1 {
    font-size: 1.2em;
    border-bottom: 1px solid #000000;
    margin: 0px;
}

JavaScript:

PDFJS.workerSrc = 'http://seikichi.github.io/tmp/PDFJS.0.8.715/pdf.min.worker.js';

$(function () {
  var pdfData = loadPDFData();

  PDFJS.getDocument(pdfData).then(function (pdf) {
    return pdf.getPage(1);
  }).then(function (page) {
    var scale = 1;
    var viewport = page.getViewport(scale);
    var $canvas = $('#the-canvas');
    var canvas = $canvas.get(0);
    var context = canvas.getContext("2d");
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    var $pdfContainer = $("#pdfContainer");
    $pdfContainer.css("height", canvas.height + "px")
      .css("width", canvas.width + "px");

    var renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    page.render(renderContext);
    setupAnnotations(page, viewport, canvas, $('.annotationLayer'));
  });

  function setupAnnotations(page, viewport, canvas, $annotationLayerDiv) {
    var canvasOffset = $(canvas).offset();
    var promise = page.getAnnotations().then(function (annotationsData) {
      viewport = viewport.clone({
        dontFlip: true
      });

      for (var i = 0; i < annotationsData.length; i++) {
        var data = annotationsData[i];
        var annotation = PDFJS.Annotation.fromData(data);
        if (!annotation || !annotation.hasHtml()) {
          continue;
        }

        var element = annotation.getHtmlElement(page.commonObjs);
        data = annotation.getData();
        var rect = data.rect;
        var view = page.view;
        rect = PDFJS.Util.normalizeRect([
          rect[0],
          view[3] - rect[1] + view[1],
          rect[2],
          view[3] - rect[3] + view[1]]);
        element.style.left = (canvasOffset.left + rect[0]) + 'px';
        element.style.top = (canvasOffset.top + rect[1]) + 'px';
        element.style.position = 'absolute';

        var transform = viewport.transform;
        var transformStr = 'matrix(' + transform.join(',') + ')';
        CustomStyle.setProp('transform', element, transformStr);
        var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
        CustomStyle.setProp('transformOrigin', element, transformOriginStr);

        if (data.subtype === 'Link' && !data.url) {
          // In this example,  I do not handle the `Link` annotations without url.
          // If you want to handle those annotations, see `web/page_view.js`.
          continue;
        }
        $annotationLayerDiv.append(element);
      }
    });
    return promise;
  }
});

function loadPDFData() {
  /*jshint multistr: true */
  var base64pdfData = '...'; //should contain base64 representing the PDF

  function base64ToUint8Array(base64) {
    var raw = atob(base64);
    var uint8Array = new Uint8Array(new ArrayBuffer(raw.length));
    for (var i = 0, len = raw.length; i < len; ++i) {
      uint8Array[i] = raw.charCodeAt(i);
    }
    return uint8Array;
  }
  return base64ToUint8Array(base64pdfData);
}

共享资源和 Fiddle 不起作用了。你能更新一下内容吗? - Jeevanantham

0
 setupAnnotations = (page, viewport, canvas, annotationLayerDiv) => {
        let pdfjsLib = window['pdfjs-dist/build/pdf'];
        let pdfjsViewer = window['pdfjs-dist/web/pdf_viewer'];

        //BELOW--------- Create Link Service using pdf viewer
        let pdfLinkService = new pdfjsViewer.PDFLinkService();

        page.getAnnotations().then(function (annotationsData) {
            viewport = viewport.clone({
                dontFlip: true
            });

            let pdf_canvas = canvas;
          
            // Render the annotation layer
            annotationLayerDiv.style.left = pdf_canvas.offsetLeft + 'px';
            annotationLayerDiv.style.top = pdf_canvas.offsetTop + 'px';
            annotationLayerDiv.style.height = viewport.height + 'px';
            annotationLayerDiv.style.width = viewport.width + 'px';

            pdfjsLib.AnnotationLayer.render({
                viewport: viewport,
                div: annotationLayerDiv,
                annotations: annotationsData,
                page: page,
                linkService: pdfLinkService,
                enableScripting: true,
                renderInteractiveForms: true
            });
    }

IMP ---- 别忘了添加这个CSS

.annotation-layer{
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  opacity: 1;
}

.annotation-layer section{
  position: absolute;
  cursor: pointer;
}

.annotation-layer section a{
  display: block;
  width: 100%;
  height: 10px;
}

在上面的例子中,链接服务实例是使用pdf查看器中的类创建的,并作为参数传递给注释层渲染方法。 请参考PDF.js的源代码,参考/web/pdf_viewer.js - 类PDFLinkService以获取更多信息。
PDF.js版本-v2.9.359

您能否扩展这个新的示例,以便包含您正在引用的脚本,以使查看器和pdflinkservice引用正常工作? - Dan
我无法使用PDFLinkService,因为在viewer.js中没有这样的类。我已经从pdf.js的github复制了pdf_link_service代码到我的项目中,但它无法找到和导入“pdfjs-lib”,我无法让它工作,你能否请解释一下如何做? :( 我无法实现注释,但我真的需要它,如果您现在能够解释如何做,我将不胜感激,因为我认为pdf.js中某些东西已经改变了。 - bzmind
@SMH 我还没有尝试过新版本的pdf.js,看起来有些东西已经改变了,不过你可以在web文件夹中找到pdf_link_service.js文件,你可以尝试使用它。 - Pranjal Koshti
@PranjalKoshti 是的,我在 pdf.js 的 Github 上询问后解决了这个问题。他们真的不希望我们直接使用那些文件(pdf_link_service.js),所以他建议我查看他们的示例组件,并像他们一样通过 pdf_viewer.js 访问 pdfLinkService。这是示例组件的链接:https://github.com/mozilla/pdf.js/tree/master/examples/components 我正在按照他们的 pageViewer.js 示例进行操作,所以您只需通过 HTML 文件中的 script 标签添加 pdf_viewer.js,然后像示例文件一样在脚本中使用即可。 - bzmind

0

启用PDF.JS中的文本选择


步骤1:添加一个元素来容纳文本层

<div id="text-layer"></div>

这个 div 将会添加到 PDF 渲染的元素中,因此 HTML 将会像这样:

<canvas id="pdf-canvas"></canvas>
<div id="text-layer"></div>

步骤二:为文本层添加CSS

将以下内容添加到您的CSS文件中:

#text-layer { 
   position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    opacity: 0.2;
    line-height: 1.0;
}

#text-layer > div {
    color: transparent;
    position: absolute;
    white-space: pre;
    cursor: text;
    transform-origin: 0% 0%;
}

第三步:获取PDF文本

在PDF文件已经被渲染到画布中后,您需要获取PDF文本内容,并将该文本放置在文本层中。

// page is the page context of the PDF page
// viewport is the viewport required in renderContext
// For more see https://usefulangle.com/post/20/pdfjs-tutorial-1-preview-pdf-during-upload-wih-next-prev-buttons    

page.render(renderContext).then(function() {
    // Returns a promise, on resolving it will return text contents of the page
    return page.getTextContent();
}).then(function(textContent) {
     // PDF canvas
    var pdf_canvas = $("#pdf-canvas"); 

    // Canvas offset
    var canvas_offset = pdf_canvas.offset();

    // Canvas height
    var canvas_height = pdf_canvas.get(0).height;

    // Canvas width
    var canvas_width = pdf_canvas.get(0).width;

    // Assign CSS to the text-layer element
    $("#text-layer").css({ left: canvas_offset.left + 'px', top: canvas_offset.top + 'px', height: canvas_height + 'px', width: canvas_width + 'px' });

    // Pass the data to the method for rendering of text over the pdf canvas.
    PDFJS.renderTextLayer({
        textContent: textContent,
        container: $("#text-layer").get(0),
        viewport: viewport,
        textDivs: []
    });
});

来源:https://usefulangle.com/post/90/javascript-pdfjs-enable-text-layer


2
这个回答对这个问题没有帮助,他想要超链接,而不是文本层。你应该使用page.getAnnotations。 - Yan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接