- takeaway
I spent part of my time studying the application of PDF.js in React, and wrote five articles to record my learning achievements. I realized simple PDF preview, page-turning and zooming in the toolbar, simple text copying functions, and optimized the slow rendering in the case of a large number of pages by using the virtual DOM. But there is a key function is not implemented PDF text search function, this article we will implement this function
Recommended reading
- 1. How to display PDF elegantly in front page: Principle description
- 2, front-end page how elegant display PDF (1) : render page
- 3, front-end page how elegant display PDF (middle) : render text
- 4. How to display PDF gracefully in front page (below) : Add toolbar
- 5. How to display PDF gracefully in front page: Virtual Scrolling
Modify render mode
If you have read the previous articles, you will know that our previous rendering method is to create a canvas tag to carry the PDF and render it to the created canvas by using pdf.render(). If you need to render the text of the PDF, you need to create a div with the same style as canvas to carry the text information. You can achieve PDF text inside the right click copy function.
Of course, there is more than one way to render PDF, which is not recommended by the official website, because PDF.js has implemented a PDF preview viewer that we can use directly
import { PDFLinkService, PDFFindController, PDFViewer } from 'pdfjs-dist/web/pdf_viewer'; const linkService = new PDFLinkService(); const findController = new PDFFindController({ linkService, }); const newViewer = new PDFViewer({ container: containerRef.current, linkService, useOnlyCssZoom: USE_ONLY_CSS_ZOOM, textLayerMode: TEXT_LAYER_MODE, // renderer:'svg', findController, }); linkService.setViewer(newViewer); / / set the initial scale newViewer currentScaleValue = scale;Copy the code
The above method registers a PDF preview viewer corresponding to the HTML below
<div
id="viewerContainer"
className="viewerContainer"
ref={containerRef}
>
<div
className="pdfViewer"
id="innerContainer"
/>
</div>
</div>
Copy the code
The above code I also according to the example given by PDF.js constantly groped out, some content is also a little knowledge, here only to explain what I can
newAll the above functions are contained in this viewer. This section requires the lookup function to be used in pdfController (), and passes it as a parameter to the viewer. Use behind his viewer. FindController. ExecuteCommand ('findagain', searcher); Method, and the searcher finds the object, which is explained laterCopy the code
Other Parameters
- Container displays the PDF container DOM. In this container, you need a div to display the PDF page information. The className of the div is recommended to use pdfViewer.
- LinkService does not know much, but needs ^ _ ^
- UseOnlyCssZoom Specifies whether to control page zoom using the CSS. The default value is false
- TextLayerMode Whether to display text by default, 0 is not displayed and 1 is displayed
- FindController passes in text to find the controller
There are some other parameters
- The default render type is Canvas optional SVG
- MaxCanvasPixels Maximum Canvas pixel
- EnablePrintAutoRotate Enables print rotation
If you use this viewer there are also some properties that are accessed directly through the newViewer object
- PagesCount total number of pages
- PageViewsReady Indicates whether all pages are rendered, because PDF rendering is asynchronous and some events are listened after rendering is completed
- CurrnetPageNumber Indicates the current page number
- CurrentScale Scale to scale the page using currentScaleValue
- PagesRotation Page rotation
- IsPageVisible (pageNumber) passes the pageNumber to check whether the page is invisible
That is the basic theory and parameters used to implement preview using PDFViewer()
Start coding
Go to the page to create the Viewer
const initialViewer = (url) => { const linkService = new PDFLinkService(); const findController = new PDFFindController({ linkService, }); const newViewer = new PDFViewer({ container: containerRef.current, linkService, useOnlyCssZoom: true, textLayerMode: 1, // renderer:'svg', findController, }); linkService.setViewer(newViewer); / / set the initial scale newViewer currentScaleValue = scale; const loadingTask = pdfjs.getDocument({ url }); loadingTask.promise.then(pdf => { if (pdf) { const nums = pdf.numPages setNumPages(nums) newViewer.setDocument(pdf); linkService.setDocument(pdf); Const interval = setInterval(() => {loadPdf()}, 1000); function loadPdf() { if (newViewer.pageViewsReady) { // ... Render complete operation}}}})}Copy the code
The corresponding HTML is the code above, where the Container is created by useRef
const containerRef = useRef(null)
Copy the code
Realize page turning and zooming
- Turn the page
The implementation of turning a page is to change the currentPageNumber value mentioned above
viewer.currentPageNumber = num
Copy the code
- The zoom
The way to change the scale is also to change the currentScaleValue by changing the property value
viewer.currentScaleValue = newScale;
Copy the code
The zoom parameter has a fixed format. If it is a number, it can be any number, but the zoom can also be a string, as follows:
<select value={`${scale}`} onChange={e => { const newScale = e.target.value viewer.currentScaleValue = newScale; SetScale (newScale)}} > <option value="auto"> automatic scaling </option> <option value="page-actual"> actual size </option> <option Value ="page-fit"> fit the page </option> <option value="page-width"> fit the page width </option> <option value="0.50">50%</option> <option Value ="0.75">75%</option> <option value="1">100%</option> <option value="1.25">125%</option> <option Value ="1.50">150%</option> <option value="1.75">175%</option> <option value="2">200%</option> <option value="3">300%</option> <option value="4">400%</option> </select>Copy the code
Text search
- Define the lookup object
Const [searcher = {}, setSearcher] = useState({phraseSearch: true, // findPrevious: True, // whether to loop to find highlightAll: true, // whether to highlight});Copy the code
Changes as the user enters
<input type="text" id="searchInput" onChange={e => { setSearcher({ ... searcher, query: e.target.value, }); }} / >Copy the code
Lookup by listening for carriage return events
# use Umi useKeyPress Hooks to event listeners (' enter 'event = > {viewer. FindController. ExecuteCommand (' findagain', a searcher); });Copy the code
Enter search for page jump and loop search
Other Event Monitoring
- Scroll page number, listen to scroll page number
document.addEventListener('pagechanging', function (evt) {
const page = evt.detail.pageNumber;
changePage(page)
})
const changePage = (num) => {
viewer.currentPageNumber = num
setCurrentPageNumber(num)
}
Copy the code
- Query statistics
useEffect(() => { window.addEventListener('updatefindcontrolstate', e => { setMatchesCount(e.detail.matchesCount); }); window.addEventListener('updatefindmatchescount', e => { setMatchesCount(e.detail.matchesCount); })}) matchesCount: {current: // total: //Copy the code
The source code
Github.com/LiuSandy/re…