天记录一个js库:pdf.js。主要是实现在线打开pdf功能。因为项目需求需要能在线查看pdf文档,所以就研究了一下这个控件。
有些人很好奇,在线打开pdf文档浏览器不是支持吗。是的你说的都是现代浏览器,例如谷歌,360,edg等。
但是很不幸的是我们这个项目是要使用我们最喜欢(很烦)的浏览器IE。所有要想使IE能够在线读取pdf,我就知道两种办法第一种下载Acrobat Reader插件,第二就是使用js库了。
介绍pdf.js
pdf.js是一个开源的js库。
官网:http://mozilla.github.io/pdf.js/
源码地址:https://github.com/mozilla/pdf.js
下载并解压
我们在http://mozilla.github.io/pdf.js/getting_started/#download选中版本后下载后解压会生成两个文件夹:
这两个文件夹核心文件就是build文件下的js文件,web文件是官方给写好的封装示例,你你可选择使用或者不使用。
├── LICENSE ├── build/ │ ├── pdf.js - 显示层 │ └── pdf.worker.js - 核心层 └── web/├── cmaps/ - 字符映射(由核心要求)├── compressed.tracemonkey-pldi-09.pdf - 测试 pdf├── debugger.js - 有帮助的PDF调试功能├── images/ - 观看者和注释图标的图像├── l10n.js - 汉化├── locale/ - 翻译文件├── viewer.css - viewer 页面样式├── viewer.html - viewer 页面└── viewer.js - viewer js
使用:
使用pdf.js有两种方式:
- 第一种使用官方给写好的示例,简单来说就是上面提到的下载下来的web文件夹。
- 第二种就是自己调用API自己写方法实现,相对于第一种如果自己要的效果不是很多还是自己写。也不是很复杂很容易实现。官方给的代码太多修改维护太麻烦。
使用官方示例:
使用官方示例其实就是使用pdfjs已经写好的viewer.html页面,例子:http://mozilla.github.io/pdf.js/web/viewer.html 做的功能比较全面。
简单的来说一下吧,很多人可能下载之后直接打开会报错,其实那是因为出现了两个问题:第一个是没有文件,第二个是知道写文件但是存在跨域。就会产生如下错误:
出现这个问题其实也没事,只要我们引用到项目后就不会出现了。然后是我们在使用的地方打开这个页面并且加上文件即可:
window.location.href = "../../Content/js/PDFShow/padjs/web/viewer.html?file=pdfTest.pdf";
效果展示:
自己实现分页版:
我们自己实现的话就不需要web文件夹下的东西。你就可以删除了。
自己定义实现说起来也是很简单的,官方上已经给了很多代码示例了。废话我就不说了。我就上一下我的代码吧。
首先引入pdf.js文件到页面:
<script src="~/Content/js/PDFShow/padjs/build/pdf.js"></script>
引入pdf.js之后:
//引入pdf.js之后var url = '../pdfTest.pdf';PDFJS.workerSrc = '../../Content/js/PDFShow/padjs/build/pdf.worker.js';//定义变量var pdfDoc = null,pageNum = 1,pageRendering = false,pageNumPending = null,scale = 1,canvas = document.getElementById('the-canvas'),ctx = canvas.getContext('2d');function renderPage(num) {pageRendering = true;pdfDoc.getPage(num).then(function (page) {//设置页面大小var viewport = page.getViewport(1);console.log(viewport.width);var desiredWidth = "1000";var scale = desiredWidth / viewport.width;var scaledViewport = page.getViewport(scale);//var viewport = page.getViewport(scale);canvas.height = scaledViewport.height;canvas.width = scaledViewport.width;//设置背景颜色(无效)canvas.style.backgroundColor = "red";//进行文件读取加载var renderContext = {canvasContext: ctx,viewport: scaledViewport};var renderTask = page.render(renderContext);renderTask.promise.then(function () {pageRendering = false;if (pageNumPending !== null) {// New page rendering is pending renderPage(pageNumPending);pageNumPending = null;}});});//显示总页数document.getElementById('page_num').textContent = pageNum;}//翻页方法function queueRenderPage(num) {if (pageRendering) {pageNumPending = num;} else {renderPage(num);}}function onPrevPage() {if (pageNum <= 1) {return;}pageNum--;queueRenderPage(pageNum);}//上一页监听document.getElementById('prev').addEventListener('click', onPrevPage);function onNextPage() {if (pageNum >= pdfDoc.numPages) {return;}pageNum++;queueRenderPage(pageNum);}//下一页监听document.getElementById('next').addEventListener('click', onNextPage);PDFJS.getDocument(url).then(function (pdfDoc_) {pdfDoc = pdfDoc_;document.getElementById('page_count').textContent = pdfDoc.numPages;renderPage(pageNum);});
相应html代码:
<body style="background:#404040"><div><button id="prev">上一页</button><button id="next">下一页</button><span>Page: <span id="page_num"></span> / <span id="page_count"></span></span></div><div style="width:100%;height:100%;background:#404040"><div style=" width:1000px;margin: 0 auto;"><canvas id="the-canvas"></canvas></div></div> </body>
效果展示:
自己实现不分页版:
虽然分页很好用,但是确不一定使用所有的场景,比如我就是想一次性打开所有页面然后滚动查看跟读word似的,怎么办,有办法,当然是实现不分页喽,哈哈。
分页好理解啊:根据页数读取然后把读取的内容放到画布上就好了,既然我们明白分页的原理,那么我们稍稍改造一下就是不分页了吗。
不分页:我们全部读出来放到页面不就好了吗,简单来说是这个样,但是具体思路是=》我们先获取到所有页数,然后遍历的把每一页像分页一下放到画布上展示,然后在遍历相同数量画布来对应每页的内容,最后展现出来。
好了大致的思路已经明白了下面就是撸代码:
还是不要忘记引用js文件:
<script src="~/Content/js/PDFShow/padjs/build/pdf.js"></script>
页面布局就可以这样子了:
<div style="width:100%;height:100%;background:#404040"><div id="pdf-container" style=" width:1000px;margin: 0 auto;"></div></div>
然后初始化控件吧:
<script>//引入pdf.js之后// var url = '../pdfTest.pdf';PDFJS.workerSrc = '../../Content/js/PDFShow/padjs/build/pdf.worker.js';window.onload = function () {//创建canvas方法 function createPdfContainer(id, className) {var pdfContainer = document.getElementById('pdf-container');var canvasNew = document.createElement('canvas');canvasNew.id = id;canvasNew.className = className;pdfContainer.appendChild(canvasNew);};//渲染pdf function renderPDF(pdf, i, id) {pdf.getPage(i).then(function (page) {//默认设置文档的显示大小var scale = 1.5;var viewport = page.getViewport(scale);//// 准备用于渲染的 canvas 元素// var canvas = document.getElementById(id);var context = canvas.getContext('2d');canvas.height = viewport.height;canvas.width = viewport.width;//// 将 PDF 页面渲染到 canvas 上下文中// var renderContext = {canvasContext: context,viewport: viewport};page.render(renderContext);});};//创建和pdf页数等同的canvas数 function createSeriesCanvas(num, template) {var id = '';for (var j = 1; j <= num; j++) {id = template + j;createPdfContainer(id, 'pdfClass');}}//读取pdf文件,并加载到页面中 function loadPDF(fileURL) {PDFJS.getDocument(fileURL).then(function (pdf) {//用 promise 获取页面var id = '';var idTemplate = 'cw-pdf-';var pageNum = pdf.numPages;//根据页码创建画布 createSeriesCanvas(pageNum, idTemplate);//将pdf渲染到画布上去for (var i = 1; i <= pageNum; i++) {id = idTemplate + i;renderPDF(pdf, i, id);}});}//启动loadPDF('../pdfTest.pdf');};</script>
最后上一下效果展示截图: