DF.js 是基于 HTML5 解析與渲染 PDF 的 JavaScript 庫,由 Mozilla 主導(dǎo)開源。
本文旨在介紹 PDF.js 于 Electron 里如何開始使用,實際嘗試了用其 API 或嵌入 HTML 的幾種方式。
項目采用 Electron React Antd PDF.js 來實現(xiàn),以下是從零準(zhǔn)備項目的過程。
這里用 electron-react-boilerplate[1] 模板開始 Electron React 項目。
# 獲取模板
git clone --depth=1 \
https://github.com/electron-react-boilerplate/electron-react-boilerplate \
electron-pdf-viewer
cd electron-pdf-viewer
# 設(shè)定倉庫
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
# 運(yùn)行
npm start
# 打包
npm run package
準(zhǔn)備編輯器(VSCode):
code --install-extension dbaeumer.vscode-eslint
code --install-extension dzannotti.vscode-babel-coloring
code --install-extension EditorConfig.EditorConfig
其他編輯器,可見 Editor Configuration[2]。
添加 antd 依賴:
npm install antd
之后,就可以快速布局頁面了,如下:
添加 pdfjs 依賴:
npm install pdfjs-dist
npm install -D worker-loader
此外,準(zhǔn)備 PDF 樣例進(jìn) static/,簡單用 Python 提供 HTTP 訪問:
npm run static
用于開發(fā)運(yùn)行,正式運(yùn)行可用 file:// 地址。
用 API 渲染頁面,可見官方 Examples[3]。
1. 導(dǎo)入包
import * as pdfjsLib from 'pdfjs-dist/webpack';
2. 渲染頁面
(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!');
})();
完整代碼,見 Pdfjs/index.tsx[4]。效果如下:
用 Viewer API 渲染,其在 pdfjs-dist/web/pdf_viewer 路徑下。
1. 導(dǎo)入包
import * as pdfjsLib from 'pdfjs-dist/webpack';
import { PDFViewer, EventBus } from 'pdfjs-dist/web/pdf_viewer';
import 'pdfjs-dist/web/pdf_viewer.css';
2. 布局頁面
<div className="viewer">
<div>url={url}</div>
<div>numPages={numPages}</div>
<div ref={hrRef} />
<div ref={containerRef} className="container">
<div className="pdfViewer" />
</div>
</div>
要求 absolute 定位:
.viewer {
position: relative;
.container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: scroll;
}
}
3. 渲染 PDF
const container = containerRef.current;
if (container == null) return;
if (hrRef.current) {
container.style.top = `${hrRef.current.offsetTop}px`;
}
// 監(jiān)聽事件,必須傳參 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');
});
// 創(chuàng)建 PDFViewer
const pdfViewer = new PDFViewer({
container,
eventBus,
linkService: null,
renderer: 'canvas',
l10n: null,
});
// 導(dǎo)入 Document
(async () => {
const loadingTask = pdfjsLib.getDocument(url);
const pdf = await loadingTask.promise;
pdfViewer.setDocument(pdf);
})();
完整代碼,見 PdfViewer/index.tsx[5]。效果如下:
PDF.js 提供了在線演示的 viewer.html,不過 pdfjs-dist 里沒有,要自己編譯其源碼。
編譯結(jié)果已放進(jìn) static/pdfjs/,可用 Electron Window 打開 web/viewer.html?file=x.pdf 或用 iframe 嵌入。
如果自己重新編譯,過程如下:
git clone -b master --depth=1 https://github.com/mozilla/pdf.js.git
cd pdf.js
# 安裝依賴
npm install -g gulp-cli
npm install
# 開發(fā)運(yùn)行
gulp server
# http://localhost:8888/web/viewer.html
# 編譯發(fā)布
gulp generic
# build/generic/
iframe 嵌入的話,也是打開 web/viewer.html?file=x.pdf:
<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 提供的 HTTP 地址,效果如下:
iframe 要打開本地 HTML 試了下沒成,如果想在 Electron + React 下這么用,還要研究下怎么弄。
PDF.js 可以說是 Web 渲染 PDF 的不二選擇,很多 PDF Web Viewer 庫都是基于它實現(xiàn)的。
GoCoding 個人實踐的經(jīng)驗分享,可關(guān)注公眾號!
[1] electron-react-boilerplate: https://electron-react-boilerplate.js.org/
[2] Editor Configuration: https://electron-react-boilerplate.js.org/docs/editor-configuration
[3] Examples: https://mozilla.github.io/pdf.js/examples/
[4] Pdfjs/index.tsx: https://github.com/ikuokuo/electron-pdf-viewer/blob/main/src/renderer/pages/Pdfjs/index.tsx
[5] PdfViewer/index.tsx: https://github.com/ikuokuo/electron-pdf-viewer/blob/main/src/renderer/pages/PdfViewer/index.tsx
現(xiàn)在有很多項目都是使用的swagger,將API直接寫在swagger文檔中,使用起來非常方便,并且支持在線調(diào)試。但是它不方便對外提供,這里我們找到了一種方法,可以方便的將swagger API導(dǎo)出為HTML或者PDF。
主要使用maven的兩個插件:1. swagger2markup-maven-plugin2. asciidoctor-maven-plugin
下面我們會詳細(xì)講解怎么使用他們和可能會遇到的問題。
AsciiDoc是一種文本文檔格式,用于編寫筆記,文檔,文章,書籍,電子書,幻燈片,網(wǎng)頁,手冊頁和博客。 AsciiDoc文件可以轉(zhuǎn)換為多種格式,包括HTML,PDF,EPUB,手冊頁。
AsciiDoc是高度可配置的:AsciiDoc源文件語法和后端輸出標(biāo)記(可以是幾乎任何類型的SGML / XML標(biāo)記)都可以由用戶自定義和擴(kuò)展。
AsciiDoc是免費(fèi)軟件,并根據(jù)GNU通用公共許可證版本2(GPLv2)的條款獲得許可。
AsciiDoc,它的設(shè)計初衷就是為了解決寫書規(guī)模的問題,并且是 O’Reilly 的在線出版平臺 Atlas 的推薦語言。
swagger2markup-maven-plugin這個插件可以將swagger的API轉(zhuǎn)換為ASCIIDOC或者M(jìn)ARKDOWN和CONFLUENCE_MARKUP。這里我們選擇轉(zhuǎn)換為ASCIIDOC。
在build中加入如下代碼:
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!--此處端口一定要是當(dāng)前項目啟動所用的端口-->
<swaggerInput>http://localhost:7667/v2/api-docs</swaggerInput>
<outputDir>target/docs/asciidoc/generated</outputDir>
<config>
<!-- 除了ASCIIDOC之外,還有MARKDOWN和CONFLUENCE_MARKUP可選 -->
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
</config>
</configuration>
</plugin>
版本我們用的是最新的1.3.7.
target/docs/asciidoc/generated 是生成的ASCIIDOC的目標(biāo)地址,我們會在后面將其轉(zhuǎn)換為HTML或者PDF。
運(yùn)行下面命令生成asciidoc:
mvn swagger2markup:convertSwagger2markup
有了asciidoc,我們使用asciidoctor-maven-plugin將其轉(zhuǎn)換為HTML和PDF。
Asciidoctor是一種快速,開放源代碼的文本處理器和發(fā)布工具鏈,用于將AsciiDoc內(nèi)容轉(zhuǎn)換為HTML5,DocBook,PDF和其他格式。 Asciidoctor用Ruby編寫,可在所有主要操作系統(tǒng)上運(yùn)行。
Asciidoctor提供了一個asciidoctor-maven-plugin,可以方便的在maven環(huán)境使用。其配置如下:
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.0.0-RC.1</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.18</version>
</dependency>
<!-- Comment this section to use the default jruby artifact provided by the plugin -->
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>9.2.7.0</version>
</dependency>
<!-- Comment this section to use the default AsciidoctorJ artifact provided by the plugin -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>src/docs/asciidoc</sourceDirectory>
<!-- Attributes common to all output formats -->
<attributes>
<sourcedir>target/docs/asciidoc/generated</sourcedir>
</attributes>
</configuration>
<executions>
<execution>
<id>generate-pdf-doc</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<!-- Since 1.5.0-alpha.9 PDF back-end can use 'rouge' as well as 'coderay'
for source highlighting -->
<!-- Due to a known issue on windows, it is recommended to use 'coderay' until an new version of 'rouge' is released.
-->
<sourceHighlighter>coderay</sourceHighlighter>
<attributes>
<icons>font</icons>
<pagenums/>
<toc/>
<idprefix/>
<idseparator>-</idseparator>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
運(yùn)行下面命令生成HTML和PDF:
mvn generate-resources
上面講到了,Asciidoctor是基于ruby的,有了asciidoc之后,我們也可以直接使用Asciidoctor的命令行來進(jìn)行轉(zhuǎn)換。步驟如下:
Asciidoctor可以處理全范圍的UTF-8字符的字符集。這意味著你可以寫你的文檔中的任何語言,使用UTF-8編碼的文件,并期望Asciidoctor到文本正確轉(zhuǎn)換。但是,您可能會注意到PDF中缺少某些語言的某些字符,例如中文。
如果您使用非拉丁語書寫,則需要使用專門的主題來提供必要的字體。例如,以從寫在CJK語言文檔的PDF如中國,你需要使用一個CJK主題。您可以通過安裝asciidoctor-pdf-cjk-kai_gen_gothic gem獲得這樣的主題。
采用專用的主題,是因為PDF需要你自己提供字體來為所有字符提供字形。沒有一種字體可以支持世界上所有的語言(盡管像Noto Serif之類的語言肯定會比較接近)。
因此,我們采取的策略是針對每個語言家族(例如CJK)創(chuàng)建單獨的專用主題。當(dāng)然,您可以自由地遵循這種模式,并使用選擇的字體來創(chuàng)建自己的主題。
怎么創(chuàng)建主題這里就不詳細(xì)講解了,有興趣的小伙伴可以自行查閱有關(guān)資料。
如何安裝:
gem install asciidoctor-pdf-cjk-kai_gen_gothic
下載字體:asciidoctor-pdf-cjk-kai_gen_gothic-install
這個主題支持以下幾種字體:
使用下面的命令來轉(zhuǎn)換PDF:
asciidoctor-pdf -r asciidoctor-pdf-cjk-kai_gen_gothic -a pdf-style=THEME doc.asc
這里我遇到了一個問題,如果字體選擇KaiGenGothicCN, 那么會在運(yùn)行時候報錯:
undefined method `strip_extended' for nil:NilClass
Use --trace for backtrace
詳細(xì)查看–trace,會發(fā)現(xiàn)報錯的是ttfunk/table/name.rb:
@postscript_name = @strings[6].first.strip_extended
從字體中獲取到的@strings[6]是空。 那么怎么辦呢?
很簡單,使用KaiGenGothicTW字體即可。
那么有了命令行,我們怎么在maven中使用呢?
請使用如下的XML配置:
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<outputDirectory>target/docs/asciidoc/pdf</outputDirectory>
<attributes>
<pdf-stylesdir>/Library/Ruby/Gems/2.3.0/gems/asciidoctor-pdf-cjk-kai_gen_gothic-0.1.1/data/themes</pdf-stylesdir>
<pdf-style>KaiGenGothicTW</pdf-style>
<pdf-fontsdir>/Library/Ruby/Gems/2.3.0/gems/asciidoctor-pdf-cjk-kai_gen_gothic-0.1.1/data/fonts</pdf-fontsdir>
<icons>font</icons>
<pagenums/>
<toc/>
<idprefix/>
<idseparator>-</idseparator>
</attributes>
</configuration>
</execution>
請關(guān)注如下幾個字段:
pdf-stylesdir:你安裝的中文主題的目錄pdf-style:中文主題的名稱pdf-fontsdir: 中文主題字體的名稱。
好了,本文講到這里,有疑問的小伙伴可以發(fā)郵件或者留言提問。謝謝。
更多教程請參考 flydean的博客
今,html5開發(fā)成了很多年輕人都想學(xué)習(xí)的軟件開發(fā)技術(shù),越來越多的年輕人想從事html5開發(fā),而html5的薪資也是一路都在飆升,想學(xué)好這門技術(shù),好的學(xué)習(xí)資料必不可少,重慶千鋒的html5基礎(chǔ)視頻教程百度網(wǎng)盤免費(fèi)分享給大家。
千鋒html5教程第1部分:課程體系解 http://pan.baidu.com/s/1o7B9OYA
千鋒html5教程第2部分:微案例講解 https://pan.baidu.com/s/1nwyNFg1
千鋒H5視頻教程第3部分:知識點講解http://pan.baidu.com/s/1jICHs9o
千鋒Vue組件之手機(jī)通訊錄實戰(zhàn)課程 http://pan.baidu.com/s/1c1FrXLY
千鋒微信小程序基礎(chǔ)與實戰(zhàn) https://pan.baidu.com/s/1xE35SQcvW0sCF2NoR_ONiw
隨著html5技術(shù)越來越成熟,越來越多的行業(yè)巨頭也在不斷向html5示好。在未來幾年,html5將會以更多的形式滲透到我們生活中的方方面面,因此越來越多的從業(yè)者開始關(guān)注html5開發(fā)行業(yè)。那么想要學(xué)好html5前端開發(fā),需要掌握的專業(yè)技術(shù)有:
第1階段:前端頁面重構(gòu):PC端網(wǎng)站布局、html5+CSS3基礎(chǔ)項目、WebAPP頁面布局;
第2階段:JavaScript高級程序設(shè)計:原生JavaScript交互功能開發(fā)、面向?qū)ο箝_發(fā)與ES5/ES6、JavaScript工具庫自主研發(fā);
第3階段:PC端全棧項目開發(fā):jQuery經(jīng)典特效交互開發(fā)、HTTP協(xié)議,Ajxa進(jìn)階與后端開發(fā)、前端工程化與模塊化應(yīng)用、PC端網(wǎng)站開發(fā)、PC端管理信息系統(tǒng)前端開發(fā);
第4階段:移動端webAPP開發(fā):Touch端項目、微信場景項目、應(yīng)用Vue.js開發(fā)WebApp項目、應(yīng)用Ionic開發(fā)WebApp項目、應(yīng)用React.js開發(fā)WebApp;
第5階段:混合(Hybrid)開發(fā):各類混合應(yīng)用開發(fā);
第6階段:NodeJS全棧開發(fā):WebApp后端系統(tǒng)開發(fā);
第7階段:大數(shù)據(jù)可視化:數(shù)據(jù)可視化入門、D3.jS詳解及項目實戰(zhàn)。
2018年千鋒教育全棧html5+課程大綱V10.0全面升級
html5課程升級后優(yōu)勢
課程大綱升級后,覆蓋熱門大數(shù)據(jù)可視化內(nèi)容,深度貫穿前端后端開發(fā),緊貼主流企業(yè)一線需求,注重項目和實戰(zhàn)能力,真正做到項目制教學(xué),業(yè)內(nèi)罕見。
課程特色:注重全棧思維培養(yǎng)
全棧html5工程師不止是技術(shù)層面,千鋒著力培養(yǎng)學(xué)員的大前端視角與全棧思維,就業(yè)后不僅有能力解決工作中的疑難問題,更有實力勝任項目leader!
html5課程升級內(nèi)容
1.新增時下大熱的大數(shù)據(jù)可視化內(nèi)容
2.深化PHP+MySQL開發(fā)內(nèi)容
3.20大項目驅(qū)動教學(xué)
如果你想快速入門html5又沒有更好的學(xué)習(xí)方法的話,建議你去千鋒教育免費(fèi)試聽試學(xué)課程,千鋒為所有學(xué)員提供了長達(dá)2周的課程試聽,不滿意不收費(fèi),讓你先了解再學(xué)習(xí),這樣的學(xué)習(xí)方式可以讓你省去更多的后顧之憂。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。