Skip to content

Instantly share code, notes, and snippets.

@yurydelendik
Last active June 18, 2024 11:46
Show Gist options
  • Save yurydelendik/f2b846dae7cb29c86d23 to your computer and use it in GitHub Desktop.
Save yurydelendik/f2b846dae7cb29c86d23 to your computer and use it in GitHub Desktop.
PDF.js get/show hightlight
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 viewport = page.viewport;
var selected = selectionRects.map(function (r) {
return viewport.convertToPdfPoint(r.left - pageRect.x, r.top - pageRect.y).concat(
viewport.convertToPdfPoint(r.right - pageRect.x, r.bottom - pageRect.y));
});
return {page: pageIndex, coords: selected};
}
function showHighlight(selected) {
var pageIndex = selected.page;
var page = PDFViewerApplication.pdfViewer.getPageView(pageIndex);
var pageElement = page.canvas.parentElement;
var viewport = page.viewport;
selected.coords.forEach(function (rect) {
var bounds = viewport.convertToViewportRectangle(rect);
var el = document.createElement('div');
el.setAttribute('style', 'position: absolute; background-color: pink;' +
'left:' + Math.min(bounds[0], bounds[2]) + 'px; top:' + Math.min(bounds[1], bounds[3]) + 'px;' +
'width:' + Math.abs(bounds[0] - bounds[2]) + 'px; height:' + Math.abs(bounds[1] - bounds[3]) + 'px;');
pageElement.appendChild(el);
});
}
@achapman009
Copy link

I am getting this weird overflow with this approach any idea why this might be the case?
the pdf viewer I am using is ngx-extended-pdf-viewer
image

@shessafridi I am having this same issue. Did you ever resolve this?

As far as i remember this problem is caused by the textLayerMode property. You can try this property by giving 2 value.

const pdfViewer = new pdfjsViewer.PDFViewer({
  container,  
  eventBus,  
  linkService,  
  textLayerMode: 2  
})

This is the correct answer. Fixed all issues.

@arty-ms
Copy link

arty-ms commented Nov 2, 2023

This solution is not useful for several reasons:

  1. It is an overlay on the top of the text, so it changes the view(color) of the text.
  2. On the tablets it will work with problems.
  3. The pdf.js TextLayer is rendered with incorrect fonts. That's why your highlight may be in incorrect place.
    The smooth way would be to make highlight using canvas. You need to construct charsMap of all characters rendered on the canvas by pdf.js. Then on mouse move you will need to find the char in charsMap and re-draw text with background on the top of pdf.js canvas. This drawing should be done in separate custom canvas.

@Mowmowj
Copy link

Mowmowj commented Jan 12, 2024

This solution is not useful for several reasons:

  1. It is an overlay on the top of the text, so it changes the view(color) of the text.
  2. On the tablets it will work with problems.
  3. The pdf.js TextLayer is rendered with incorrect fonts. That's why your highlight may be in incorrect place.
    The smooth way would be to make highlight using canvas. You need to construct charsMap of all characters rendered on the canvas by pdf.js. Then on mouse move you will need to find the char in charsMap and re-draw text with background on the top of pdf.js canvas. This drawing should be done in separate custom canvas.

Hi, I am working on this recently, I would like to discuss this with you.
About your problem :
No.1 you could add a svg layer under text layer to use rect to render the highlighted element then the text layer will not be changed.
No.2 curious to know why can't it work on tablet? cuz touch or something? (as i know ios selection have problem.)
No.3 you are right the text layer position is not 100% same with canvas text position. the canvas solution is great as i find the "apryse"(but it not open source and need pay) seems to use this solution. But I am not sure how much work need to do of this by self.

@dieggop
Copy link

dieggop commented Apr 26, 2024

Is possible to get only position of click on document? in points?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment