如何使用pdf.js进行搜索?

19

我正在我的Ionic应用程序中使用pdf.js显示pdf文件。我没有使用viewer.js和viewer.html,因为我需要完全不同的布局。现在我有一个自定义搜索栏,我想在我的pdf文件中突出显示术语。是否有一个函数可以调用来实现这个功能?

我是这样呈现文件的:

$scope.renderPages = function(pdfDoc) {
    $scope.pdfFile = pdfDoc;
    for(var num = 1; num <= pdfDoc.numPages; num++){
        pdfDoc.getPage(num).then($scope.renderPage);
    }
}

$scope.renderPage = function(page) {
    var viewport = page.getViewport(1);
    scale = document.getElementById('viewer').clientWidth / viewport.width;
    viewport = page.getViewport(scale);

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var renderContext = {
        canvasContext: ctx,
        viewport: viewport
    };

    canvas.height = viewport.height;
    canvas.width = viewport.width;

    var canvasContainer = document.getElementById('viewer');
    canvasContainer.appendChild(canvas);

    page.render(renderContext);
}

HTML:

<div id="viewerContainer" style="padding-bottom: 100%; padding-top: 20px;">
    <div id="viewer" class="viewer-styles">
    </div>
</div>

1
取决于您想如何处理结果。如果您只是想查找页面,请使用page.getTextContent()。但如果您想显示结果,请查看examples/components并使用PDFFindController。 - async5
1
谢谢你的回答!我尝试理解PDFFindController,但它似乎很复杂。不幸的是,我没有找到任何如何使用它的示例。你知道有好的教程吗? - chocolate cake
我认为你不需要理解逻辑,只需要找到它在Web/文件中的使用方式。 - async5
2个回答

30

现在我找到了解决方法!

var container = document.getElementById('viewerContainer');
var viewer = document.getElementById('viewer');


var pdfViewer = new PDFViewer({ 
   container: container,
   viewer: viewer
});

$scope.pdfFindController = new PDFFindController({
   pdfViewer: pdfViewer
);

pdfViewer.setFindController($scope.pdfFindController);

container.addEventListener('pagesinit', function () {
    pdfViewer.currentScaleValue = 'page-width';                            
});

PDFJS.getDocument(MY_PATH_TO_THE_PDF).then(function (pdfDocument) {
    pdfViewer.setDocument(pdfDocument);
});

搜索术语:

$scope.pdfFindController.executeCommand('find', {
    caseSensitive: false, 
    findPrevious: undefined,
    highlightAll: true, 
    phraseSearch: true, 
    query: "myQuery"
});

我必须导入viewer.js。

我在问题中发布的代码不再需要。PDFViewer会渲染PDF文档。


1
@chocolate_cake,这个救了我的一天 :) 你找到了一种方法来识别包含搜索结果的页面编号,以便仅显示该页面吗?或者,另外一种方法是将焦点定位到高亮文本上?我可以看到在pdf_find_controller.js(https://searchcode.com/codesearch/view/58844381/)中定义了matchCount和pageMatches数组,但我无法弄清楚如何访问它们;即使在文档加载并正确显示高亮之后,pdfFindController.matchCount也返回零。谢谢 :) - jmng
2
你好@derelict!我很高兴能帮到你。我更改了pdfjs,使其只显示一页,并在此页面上搜索(原因:移动设备的性能问题)。我认为匹配数组是正确的方法,但我没有尝试过这样做。也许你可以通过计算pdfLength * pageNumber或类似的方式来获取滚动长度并向下滚动? - chocolate cake
3
只是好奇,你是通过什么样的文档来解决viewer.js工具的问题的?我在使用通用的viewer.html页面之外使用该工具时遇到了麻烦。 - Will P.
2
在哪里可以找到viewer.js? - user3217883
2
看起来 setFindController 方法已经被弃用了。请使用:var findController = PDFViewer.findController; findController.executeCommand(...) - Philipp Nies
显示剩余6条评论

6

这是一个旧的线程,不过我想人们现在应该知道包是如何工作的。我已经成功地让它以以下方式工作。我使用了一个iframe来显示pdf。

const iframeDocument = document.getElementById('pdf-js-viewer').contentWindow;
let searchText = "TheTextYouWantoToHighlight";

iframeDocument.PDFViewerApplication.pdfViewer.findController.executeCommand('find', {
    caseSensitive: false, 
    findPrevious: undefined,
    highlightAll: true, 
    phraseSearch: true, 
    query: searchText
})

使用最新版本的pdfjs,此代码可以正常工作,但会在控制台中显示错误提示使用dispatch event。这段代码将消除该错误并按预期工作。

const iframeDocument = document.getElementById('pdf-js-viewer').contentWindow;
let searchText = "TheTextYouWantoToHighlight";
iframeDocument.PDFViewerApplication.eventBus.dispatch('find', {
    caseSensitive: false,
    findPrevious: undefined,
    highlightAll: true,
    phraseSearch: true,
    query: searchText
});

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