PDF.js Electron Viewer

PDF.js 是基于 HTML5 解析与渲染 PDF 的 JavaScript 库,由 Mozilla 主导开源。

本文旨在介绍 PDF.jsElectron 里如何开始使用,实际尝试了用其 API 或嵌入 HTML 的几种方式。

从零准备项目

项目采用 Electron React Antd PDF.js 来实现,以下是从零准备项目的过程。

Electron React

这里用 electron-react-boilerplate 模板开始 Electron React 项目。

1# 获取模板 2git clone --depth=1 \ 3https://github.com/electron-react-boilerplate/electron-react-boilerplate \ 4electron-pdf-viewer 5 6cd electron-pdf-viewer 7 8# 设定仓库 9git remote set-url origin git@github.com:ikuokuo/electron-pdf-viewer.git 10# 如果想合并成一个初始提交 11# https://stackoverflow.com/a/23486788 12git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f' 13git squash-all "first commit" 14git push -u origin main
1# 依赖 2npm install 3# 运行 4npm start 5# 打包 6npm run package

准备编辑器(VSCode):

1code --install-extension dbaeumer.vscode-eslint 2code --install-extension dzannotti.vscode-babel-coloring 3code --install-extension EditorConfig.EditorConfig

其他编辑器,可见 Editor Configuration

Ant Design

添加 antd 依赖:

1npm install antd

之后,就可以快速布局页面了,如下:

PDF.js

添加 pdfjs 依赖:

1npm install pdfjs-dist 2npm install -D worker-loader

此外,准备 PDF 样例进 static/,简单用 Python 提供 HTTP 访问:

1npm run static

用于开发运行,正式运行可用 file:// 地址。

PDF.js 渲染

使用 API

用 API 渲染页面,可见官方 Examples

1. 导入包

1import * as pdfjsLib from 'pdfjs-dist/webpack';

2. 渲染页面

1(async () => { 2 // 获取 doc 3 const loadingTask = pdfjsLib.getDocument(url); 4 const pdf = await loadingTask.promise; 5 6 console.log(`PDF loaded, n=${pdf.numPages}`); 7 setNumPages(pdf.numPages); 8 9 // 获取 page 10 const page = await pdf.getPage(1); 11 12 // 获取 canvas 13 14 const scale = 1.5; 15 const viewport = page.getViewport({ scale }); 16 // Support HiDPI-screens. 17 const outputScale = window.devicePixelRatio || 1; 18 19 const canvas = canvasRef.current; 20 if (canvas == null) return; 21 const context = canvas.getContext('2d'); 22 23 canvas.width = Math.floor(viewport.width * outputScale); 24 canvas.height = Math.floor(viewport.height * outputScale); 25 canvas.style.width = `${Math.floor(viewport.width)}px`; 26 canvas.style.height = `${Math.floor(viewport.height)}px`; 27 28 const transform = 29 outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null; 30 31 // 渲染 page 32 const renderContext = { 33 canvasContext: context, 34 transform, 35 viewport, 36 }; 37 await page.render(renderContext); 38 console.log('Page rendered!'); 39})();

完整代码,见 Pdfjs/index.tsx。效果如下:

使用 Viewer API

用 Viewer API 渲染,其在 pdfjs-dist/web/pdf_viewer 路径下。

1. 导入包

1import * as pdfjsLib from 'pdfjs-dist/webpack'; 2import { PDFViewer, EventBus } from 'pdfjs-dist/web/pdf_viewer'; 3import 'pdfjs-dist/web/pdf_viewer.css';

2. 布局页面

1<div className="viewer"> 2 <div>url={url}</div> 3 <div>numPages={numPages}</div> 4 <div ref={hrRef} /> 5 <div ref={containerRef} className="container"> 6 <div className="pdfViewer" /> 7 </div> 8</div>

要求 absolute 定位:

1.viewer { 2 position: relative; 3 4 .container { 5 position: absolute; 6 top: 0; 7 left: 0; 8 right: 0; 9 bottom: 0; 10 overflow: scroll; 11 } 12}

3. 渲染 PDF

1const container = containerRef.current; 2if (container == null) return; 3 4if (hrRef.current) { 5 container.style.top = `${hrRef.current.offsetTop}px`; 6} 7 8// 监听事件,必须传参 PDFViewer 为实例 9const eventBus = new EventBus(null); 10eventBus.on('pagesinit', () => { 11 console.log('pagesinit'); 12}); 13// eslint-disable-next-line @typescript-eslint/no-explicit-any 14eventBus.on('pagesloaded', (e: any) => { 15 console.log('pagesloaded'); 16 console.log(e); 17 setNumPages(e.pagesCount); 18}); 19eventBus.on('pagerendered', () => { 20 console.log('pagerendered'); 21}); 22 23// 创建 PDFViewer 24const pdfViewer = new PDFViewer({ 25 container, 26 eventBus, 27 linkService: null, 28 renderer: 'canvas', 29 l10n: null, 30}); 31 32// 导入 Document 33(async () => { 34 const loadingTask = pdfjsLib.getDocument(url); 35 const pdf = await loadingTask.promise; 36 pdfViewer.setDocument(pdf); 37})();

完整代码,见 PdfViewer/index.tsx。效果如下:

使用 Viewer HTML

PDF.js 提供了在线演示的 viewer.html,不过 pdfjs-dist 里没有,要自己编译其源码。

编译结果已放进 static/pdfjs/,可用 Electron Window 打开 web/viewer.html?file=x.pdf 或用 iframe 嵌入。

如果自己重新编译,过程如下:

1git clone -b master --depth=1 https://github.com/mozilla/pdf.js.git 2cd pdf.js 3 4# 安装依赖 5npm install -g gulp-cli 6npm install 7 8# 开发运行 9gulp server 10# http://localhost:8888/web/viewer.html 11 12# 编译发布 13gulp generic 14# build/generic/

iframe 嵌入的话,也是打开 web/viewer.html?file=x.pdf

1<div className="viewerHTML"> 2 <div>pdfUrl={pdfUrl}</div> 3 <div>pdfWebViewerUrl={pdfWebViewerUrl}</div> 4 <iframe 5 className="pdfViewer" 6 title="PdfViewerHTML" 7 src={`${pdfWebViewerUrl}?file=${pdfUrl}`} 8 /> 9</div>
1.viewerHTML { 2 .pdfViewer { 3 border: none; 4 width: 100%; 5 height: 100%; 6 } 7}

这里打开的 npm run static 提供的 HTTP 地址,效果如下:

iframe 要打开本地 HTML 试了下没成,如果想在 Electron + React 下这么用,还要研究下怎么弄。

最后

PDF.js 可以说是 Web 渲染 PDF 的不二选择,很多 PDF Web Viewer 库都是基于它实现的。

GoCoding 个人实践的经验分享,可关注公众号!

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )