PDF.js is a JavaScript library based on HTML5 to parse and render PDF, and is led by Mozilla to open source.
This article aims to introduce PDF.js in Electron , and actually tried several ways to use its API or embed HTML.
Prepare the project from scratch
The project is implemented using Electron React Antd PDF.js. The following is the process of preparing the project from scratch.
Electron React
Here use the electron-react-boilerplate template to start the Electron React project.
# 获取模板
git clone --depth=1 \
https://github.com/electron-react-boilerplate/electron-react-boilerplate \
electron-pdf-viewer
cd electron-pdf-viewer
# 设定仓库
git remote set-url origin git@github.com:ikuokuo/electron-pdf-viewer.git
# 如果想合并成一个初始提交
# https://stackoverflow.com/a/23486788
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
git squash-all "first commit"
git push -u origin main
# 依赖
npm install
# 运行
npm start
# 打包
npm run package
Prepare the editor (VSCode):
code --install-extension dbaeumer.vscode-eslint
code --install-extension dzannotti.vscode-babel-coloring
code --install-extension EditorConfig.EditorConfig
For other editors, see Editor Configuration .
Ant Design
Add antd
dependency:
npm install antd
After that, you can quickly layout the page, as follows:
PDF.js
Add pdfjs
dependency:
npm install pdfjs-dist
npm install -D worker-loader
In addition, prepare the PDF sample into static/
, and simply use Python to provide HTTP access:
npm run static
For development and operation, the address of file://
PDF.js rendering
Use API
Use the API to render the page, see the official Examples .
1. Import the package
import * as pdfjsLib from 'pdfjs-dist/webpack';
2. Render the page
(async () => {
// 获取 doc
const loadingTask = pdfjsLib.getDocument(url);
const pdf = await loadingTask.promise;
console.log(`PDF loaded, n=${pdf.numPages}`);
setNumPages(pdf.numPages);
// 获取 page
const page = await pdf.getPage(1);
// 获取 canvas
const scale = 1.5;
const viewport = page.getViewport({ scale });
// Support HiDPI-screens.
const outputScale = window.devicePixelRatio || 1;
const canvas = canvasRef.current;
if (canvas == null) return;
const context = canvas.getContext('2d');
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = `${Math.floor(viewport.width)}px`;
canvas.style.height = `${Math.floor(viewport.height)}px`;
const transform =
outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null;
// 渲染 page
const renderContext = {
canvasContext: context,
transform,
viewport,
};
await page.render(renderContext);
console.log('Page rendered!');
})();
For the complete code, see Pdfjs/index.tsx . The effect is as follows:
Use Viewer API
Render with the Viewer API, which is in the path pdfjs-dist/web/pdf_viewer
1. Import the package
import * as pdfjsLib from 'pdfjs-dist/webpack';
import { PDFViewer, EventBus } from 'pdfjs-dist/web/pdf_viewer';
import 'pdfjs-dist/web/pdf_viewer.css';
2. Layout page
<div className="viewer">
<div>url={url}</div>
<div>numPages={numPages}</div>
<div ref={hrRef} />
<div ref={containerRef} className="container">
<div className="pdfViewer" />
</div>
</div>
Request absolute
positioning:
.viewer {
position: relative;
.container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: scroll;
}
}
3. Render PDF
const container = containerRef.current;
if (container == null) return;
if (hrRef.current) {
container.style.top = `${hrRef.current.offsetTop}px`;
}
// 监听事件,必须传参 PDFViewer 为实例
const eventBus = new EventBus(null);
eventBus.on('pagesinit', () => {
console.log('pagesinit');
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eventBus.on('pagesloaded', (e: any) => {
console.log('pagesloaded');
console.log(e);
setNumPages(e.pagesCount);
});
eventBus.on('pagerendered', () => {
console.log('pagerendered');
});
// 创建 PDFViewer
const pdfViewer = new PDFViewer({
container,
eventBus,
linkService: null,
renderer: 'canvas',
l10n: null,
});
// 导入 Document
(async () => {
const loadingTask = pdfjsLib.getDocument(url);
const pdf = await loadingTask.promise;
pdfViewer.setDocument(pdf);
})();
For the complete code, see PdfViewer/index.tsx . The effect is as follows:
Use Viewer HTML
PDF.js provides an online demonstration of viewer.html
, but pdfjs-dist
is not in 061b9bcb24d946. You have to compile the source code yourself.
The compiled result has been put into static/pdfjs/
, you can use Electron Window to open web/viewer.html?file=x.pdf
or use iframe
embed it.
If you recompile yourself, the process is as follows:
git clone -b master --depth=1 https://github.com/mozilla/pdf.js.git
cd pdf.js
# 安装依赖
npm install -g gulp-cli
npm install
# 开发运行
gulp server
# http://localhost:8888/web/viewer.html
# 编译发布
gulp generic
# build/generic/
iframe
web/viewer.html?file=x.pdf
is also opened:
<div className="viewerHTML">
<div>pdfUrl={pdfUrl}</div>
<div>pdfWebViewerUrl={pdfWebViewerUrl}</div>
<iframe
className="pdfViewer"
title="PdfViewerHTML"
src={`${pdfWebViewerUrl}?file=${pdfUrl}`}
/>
</div>
.viewerHTML {
.pdfViewer {
border: none;
width: 100%;
height: 100%;
}
}
npm run static
opened here has the following effect:
iframe
wants to open the local HTML, but it failed. If you want to use it under Electron + React, you have to study how to do it.
At last
PDF.js can be said to be the best choice for rendering PDF on the Web. Many PDF Web Viewer libraries are based on it.
GoCoding personal practice experience sharing, please follow the official account!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。