Frage

I'm using the PDF.js library to render a pdf into the canvas. That pdf has hyperlinks in there, The PDF.js library is drawing the pdf into the canvas but the hyperlinks don't work.

Any Idea if it possible that hyperlinks work into the canvas?

Thanks

War es hilfreich?

Lösung

Here is a fiddle that shows you how to enable annotations (including hyperlinks) in PDF files. The original PDF file used in the fiddle is here.

I used viewer code (web/page_view.js,web/viewer.css) as refrence to write this fiddle.

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:

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);
}

Andere Tipps

Enable Text Selection in PDF.JS


Step 1: Adding a Element to Hold the Text Layer

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

This div will be in addition to the element where the PDF is rendered, so the HTML will look like :

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

Step 2 : Adding CSS for Text Layer

Add the following to your CSS file :

#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%;
}

Step 3: Getting the PDF Text

After the PDF has been rendered in the canvas, you need to get the text contents of the PDF, and place that text in the text layer.

// 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: []
    });
});

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

 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 ---- Do not forget to add this 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;
}

In above example, Link service instance is created using class in pdf viewer, which is being passed as parameter to annotation layer render method. Please refer source code of PDF.js refer to /web/pdf_viewer.js - class PDFLinkService for more information.

PDF.js version - v2.9.359

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top