某天測試妹子告訴我,爲啥這個pdf在ie裏打不開?而後我去瞟了一眼:css
This browser does not support inline PDFs. Please download the PDF to view it: Download PDF
複製代碼
以前沒怎麼接觸過PDF在線閱讀,這項目也是老項目,而後就去看這些傢伙到底用的什麼不兼容ie的PDF在線閱讀插件的,發現是PDFObject,然而PDFObject並不支持在沒有pdf渲染器的瀏覽器中呈現pdf
既然這樣,那麼咱們就下載一個Adobe Reader吧!等等...難道每一個客戶我都要提醒下載這個reader嗎?客戶心理不會mmp嗎?html
You can also use PDF.js to force PDF rendering in-browser without a plugin, but that's outside the scope of PDFObject.vue
學習一個新東西,從demo作起git
這次demo直接使用
vue-cli
建立github
www.jsdelivr.com/package/npm…
cdnjs.com/libraries/p…
unpkg.com/pdfjs-dist/web
npm i pdfjs-dist
複製代碼
orvue-cli
yarn add pdfjs-dist
複製代碼
import PDFJS from 'pdfjs-dist';
PDFJS.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.js';
複製代碼
爲了提高解析和渲染PDF的性能,pdf.js引入了Web Workers,不瞭解web worker的童鞋也能夠戳阮一峯老師的這篇文章npm
PDFJs經過canvas
將pdf內容渲染到瀏覽器,因此咱們須要在HTML中添加一個canvas
canvas
<canvas id="the-canvas" style="border:1px solid black"></canvas>
複製代碼
然而此方式渲染出來的PDF內容沒法被選中,怎麼辦呢?api
使用
getTextContent
獲取pdf內容,再經過TextLayerBuilder
將內容渲染到canvas
圖層之上就能夠選中了
首先調用 PDFJS.getDocument
方法獲取一個PDFDocumentLoadingTask,
getDocument (src)→{ PDFDocumentLoadingTask }
src類型能夠爲 string | TypedArray | DocumentInitParameters | PDFDataRangeTransport
,在這裏咱們直接使用string
類型,即pdf的url字符串
該方法雖然返回一個PDFDocumentLoadingTask
,可是仍然能夠像使用promise
同樣使用它,源碼以下,在調用pdf.then
的時候會返回一個Promise
對象。
class PDFDocumentLoadingTask {
/* 省略若干代碼 */
/** * @return {Promise} */
get promise() {
return this._capability.promise;
}
then(onFulfilled, onRejected) {
deprecated('PDFDocumentLoadingTask.then method, ' +
'use the `promise` getter instead.');
return this.promise.then.apply(this.promise, arguments);
}
}
複製代碼
拿到PDFDocumentLoadingTask
以後,根據pdf頁碼獲取當前頁的pdf
let pdf = await PDFJS.getDocument(url) // URL爲pdf的連接
let page = await pdf.getPage(num) // num 爲頁碼,如 1
複製代碼
設置PDf文檔的頁面尺寸(展現比例)
let scale = 1.5;
let viewport = page.getViewport(scale);
複製代碼
渲染pdf
let renderContext = {
canvasContext: context, // 此爲canvas的context
viewport: viewport
};
await page.render(renderContext); // 這裏await是爲了後面渲染pdf文本
複製代碼
而後拿到pdf的內容渲染成文本
let textContent = await page.getTextContent()
/* ... */
// 建立新的TextLayerBuilder實例
var textLayer = new TextLayerBuilder({
textLayerDiv: textLayerDiv, // 放置文本的dom
pageIndex: page.pageIndex, // pdf頁碼
viewport: viewport
});
textLayer.setTextContent(textContent);
textLayer.render();
複製代碼
完整代碼以下,接下來就是展現CV大法的時候了,能夠參考example
巴拉巴拉...
import PDFJS from "pdfjs-dist";
import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
import "pdfjs-dist/web/pdf_viewer.css";
PDFJS.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.js";
var container;
export default {
name: "HelloWorld",
props: {
msg: String
},
mounted() {
this.$nextTick(() => {
let url =
"http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf";
this.getPDF(url);
});
},
methods: {
async getPDF(url) {
let pdf = await PDFJS.getDocument(url)
container = container || document.querySelector('#container')
for(let i = 0; i < pdf.numPages; i++) {
try{
await this.rendPDF(pdf, i)
} catch(e) {
// console.error(e)
}
}
},
async renderPDF(pdf, num) {
let page = await pdf.getPage(num)
// 設置展現比例
let scale = 1.5;
let viewport = page.getViewport(scale);
let pageDiv = document.createElement('div');
pageDiv.setAttribute('id', 'page-' + (page.pageIndex + 1));
pageDiv.setAttribute('style', 'position: relative');
container.appendChild(pageDiv);
let canvas = document.createElement('canvas');
pageDiv.appendChild(canvas);
let context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
let renderContext = {
canvasContext: context,
viewport: viewport
};
await page.render(renderContext);
let textContent = await page.getTextContent()
// 建立文本圖層div
const textLayerDiv = document.createElement('div');
textLayerDiv.setAttribute('class', 'textLayer');
textLayerDiv.setAttribute('style', `width: ${viewport.width}px; margin: 0 auto;`)
// 將文本圖層div添加至每頁pdf的div中
pageDiv.appendChild(textLayerDiv);
// 建立新的TextLayerBuilder實例
var textLayer = new TextLayerBuilder({
textLayerDiv: textLayerDiv,
pageIndex: page.pageIndex,
viewport: viewport
});
textLayer.setTextContent(textContent);
textLayer.render();
}
}
};
複製代碼