2、前端頁面如何優(yōu)雅的顯示PDF(上):渲染頁面

推薦閱讀

準(zhǔn)備工作

  1. 創(chuàng)建 react 項(xiàng)目:
create-react-app
  1. 在項(xiàng)目中添加 pdf.js 依賴
npm install pdfjs-dist || yarn add pdfjs-dist

使用 pdfjs-dist

關(guān)鍵的兩個文件

  • pdf.js
  • pdf.worker.js

如何使用

import pdfjs from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

這兩個文件包含了獲取、解析和展示PDF文檔的方法,但是解析和渲染PDF需要較長的時間,可能會阻塞其它JS代碼的運(yùn)行。
為解決該問題,pdf.js依賴了HTML5引入的Web Workers——通過從主線程中移除大量CPU操作(如解析和渲染)來提升性能。

PDF.js的API都會返回一個Promise,使得我們可以優(yōu)雅的處理異步操作。但是文檔甚少,只能查找源碼,瀏覽 github

++題外話:在看別人寫的pdf渲染的項(xiàng)目使用 pdfjs-dist 的時候 這么寫的++

 pdfjs.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.js');

通過 required 引入 pdf.worker 但是使用 create-react-app 創(chuàng)建的 react 項(xiàng)目在使用的時候不能夠直接使用 required,如果這么使用會報(bào)這個錯
[圖片上傳失敗...(https://pic2.zhimg.com/80/v2-75bac6b27ae24f93cfc519c24f2c8e9f_1440w.jpg)]

查看源碼就能夠定位到問題原因:他的接受的必須是字符串

# 位置 pdf.js/src/display/worker_options.js Lines 27 to 34 in 4fe9260
/** 
  * A string containing the path and filename of the worker file. 
  * 
  * NOTE: The `workerSrc` option should always be set, in order to prevent any 
  *       issues when using the PDF.js library. 
  * @var {string} 
  */ 
 GlobalWorkerOptions.workerSrc = 

同樣的可以使用 CND 的方式解決這個問題

pdfjs.GlobalWorkerOptions.workerSrc = "https://cdn.bootcss.com/pdf.js/2.2.228/pdf.worker.js";

渲染

  1. 創(chuàng)建 canvas 以便于渲染pdf
const canvasRef = useRef(null)

<canvas
    ref={canvasRef}
    width={window.innerWidth}
    height={window.innerHeight}
/>
  1. 添加渲染PDF的 js 代碼
# 讀取 PDF 文件
const loadingTask = pdfjs.getDocument(url);

# 獲得到 PDF 對象
const pdf = await loadingTask.promise;

const firstPageNumber = 1;

# 讀取到頁面信息
const page = await pdf.getPage(firstPageNumber);

# 設(shè)置頁面縮放
const scale = 1;
const viewport = page.getViewport({scale: scale});

# 以下寫法清晰度更高
# const devicePixelRatio = window.devicePixelRatio;
# const viewport = page.getViewport({scale: scale * devicePixelRatio});


// Prepare canvas using PDF page dimensions
const canvas = canvasRef.current;

const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;

// Render PDF page into canvas context
const renderContext = {
    canvasContext: context,
    viewport: viewport
};
const renderTask = page.render(renderContext);

這樣PDF就渲染到剛才我們寫的canvas中,但是這段代碼只能渲染第一頁,通過改變 firstPageNumber 渲染不同的頁面。

getDocument():用于異步獲取PDf文檔,發(fā)送多個Ajax請求以塊的形式下載文檔。它返回一個Promise,該P(yáng)romise的成功回調(diào)傳遞一個對象,該對象包含PDF文檔的信息,該回調(diào)中的代碼將在完成PDf文檔獲取時執(zhí)行。

getPage():用于獲取PDF文檔中的各個頁面。

getViewport():針對提供的展示比例,返回PDf文檔的頁面尺寸。

render():渲染PDF。

這也寫只能滿足簡單的翻頁需求,如果增加別的需求,放大縮小,文本復(fù)制,就不能改滿足。我們下節(jié)來編寫如何能夠==文本復(fù)制==。

源碼地址:https://github.com/LiuSandy/react-pdf-render

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容