如何从pdf.js中获取用户选择的文本?

11
这个问题涉及到pdf.js,一个基于Javascript的pdf渲染器。我正在构建一个定制版本,在其中需要提取我在pdf中选择的文本。
有其他帖子可以从一页或整个pdf文档中获取文本,例如 这里,但我想抓取用户选择的特定文本,然后可能通过提示或在控制台中打印出来。
3个回答

9
你需要的是 window.getSelection() 方法。该方法返回一个特定的 Selection 对象,其范围为网页上所选文本。
以下是如何将 getSelection()pdf.js 结合使用的方法:
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);
});
}

多亏了您的建议,我实现了自己想要的功能。提供的解决方案不仅满足了我的需求,而且非常有趣。我只需要使用window.getSelection().toString()获取内部文本,并将其与事件处理程序配对即可。 :) - Srikar Reddy
2
另外,关于您提供的解决方案,在 getHighlightCoords() 中的 .map() 似乎无法正常工作,因为选择矩形即 "window.getSelection().getRangeAt(0).getClientRects();" 返回的是对象数组而不是对象,所以您需要将其转换为类似于这样的数组:**"var selectionRectsList = Object.values(selectionRects);"** - Srikar Reddy
@SrikarReddy,您能确认一下您是如何完成的吗? - Sreenath Ganga
@SrikarReddy window.getSelection().toString()并没有给我正确的选择,而是整个div的内容。你有什么提示可以获取特定的所选文本吗? - zagoa
在pdf.js 2.12中无法工作,所有坐标都是NaN。 - chitgoks

5

pdf.js在web目录下有一个文件查看器viewer.html。

在viewer.html中,您需要执行以下两个步骤:

  1. 添加选择更改事件监听器。
  2. 定义事件处理函数onselectionchange()。
<script>

  // addEventListener version
  document.addEventListener('selectionchange', () => {
    console.log(document.getSelection());
  });

  // onselectionchange version
  document.onselectionchange = () => {
    var text = getSelectedText();

    if(text)
    {
      alert(text); 

    }
  };

  function getSelectedText() {
     if (window.getSelection) {
        return window.getSelection().toString();
     } 
     else if (document.selection) {
         return document.selection.createRange().text;
     }
     return '';
  }
</script>

0
作为对chitgoks信息(在pdf.js 2.12中不起作用)的回复:
我对semanser代码进行了小的调整,并在Chrome 97和PDF.js:2.13.99中进行了测试。
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 r = selectionRects[0];
var selected = 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};
}



// addEventListener version
  document.addEventListener('selectionchange', () => {
    console.log(getHightlightCoords());
  });

这对我有效!


这个带有showHighlights功能的函数会导致div层的left、top、width和 height也变成NaN吗?因此,bounds = viewport.convertToViewportRectangle(rect) 的结果是bounds具有[NaN,NaN, NaN, NaN]。虽然我已经解决了这个用例,但我的问题在于文本选择的灵敏度。pdf.js具有textLayerMode的enable_enhanced选项,但检索到的客户端记录是错误的,但文本选择的灵敏度符合预期。 - chitgoks

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