0

I'm working on porting an experimental AngularJS app to Angular 4.

One of the key features of the app is the ability for a user to highlight text from the PDF and to get coordinates corresponding to their selection in return (a PDF is a 595x842 pixel rectangle, to keep things simple, assume the user can only select a single line of text and we return the bottom-left most corner of the selection)

In order to do this, the AngularJS app used the first function which can be found in the response here How do I retrieve text from user selection in pdf.js? and it worked perfectly. More precisely our code was

function getHightlightCoords() {
    var pageIndex = PDFViewerApplication.pdfViewer.currentPageNumber - 1;
    var page = PDFViewerApplication.pdfViewer.getPageView(pageIndex);
    var pageRect = page.canvas.getClientRects()[0];
    var selectionRects = window.getSelection().getRangeAt(0).getClientRects();
    var selectionRect = selectionRects[0]; //only care about one line, maybe forbid multi line
    var viewport = page.viewport;
    var leftAndBot = viewport.convertToPdfPoint(selectionRect.left - pageRect.x, selectionRect.top - pageRect.y);
    return leftAndBot
}

I've been trying to reproduce this behavior with the ng2-pdf-viewer package (I couldn't get pdf.js to provide searchable text with Angular 4), here's some boilerplate code to quickly get ng2-pdf-viewer working https://stackblitz.com/edit/ng2-pdf-viewer

I've been browsing the source code for a couple of hours looking for some kind of callback I could fetch coordinates from, but so far I haven't found any high level function doing this.

Has anyone ever encountered this challenge and found a way to solve it? Is this feature just not provided by this module?

Skum
  • 506
  • 5
  • 19

1 Answers1

1

I ended up working directly with the textLayer that is rendered on top of the PDF on the webpage rather than with the library itself.

I resized the pdf container to have size 595x842 with

<div class="pdf-container">
  <pdf-viewer [src]="src"
              [zoom]="0.75">
  </pdf-viewer>

Then I added the following function

public onClick(){
    const textLayer = document.getElementsByClassName('TextLayer');
    const x = window.getSelection().getRangeAt(0).getClientRects()[0].left - textLayer[0].getBoundingClientRect().left;
    const y = window.getSelection().getRangeAt(0).getClientRects()[0].top - textLayer[0].getBoundingClientRect().top;
}

As you can probably guess from the function name, I call this function with the click of a button, but of course you can call it however you like (as long as the PDF has been rendered)

Note that because of the way the text layer is rendered with PDF.JS, the coordinates of your selection may be a few pixels off the actual coordinates on the PDF of what you selected. Not much I can do about that with this approach. I will approve a new answer if somebody comes up with a better alternative.

Skum
  • 506
  • 5
  • 19