天记录一个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之后:
![](https://yqfile.alicdn.com/img_1c53668bcee393edac0d7b3b3daff1ae.gif?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_405b18b4b6584ae338e0f6ecaf736533.gif?x-oss-process=image/resize,w_1400/format,webp)
//引入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>
然后初始化控件吧:
![](https://yqfile.alicdn.com/img_1c53668bcee393edac0d7b3b3daff1ae.gif?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_405b18b4b6584ae338e0f6ecaf736533.gif?x-oss-process=image/resize,w_1400/format,webp)
<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>
最后上一下效果展示截图:
作者:YanBigFeg —— 颜秉锋
出处:http://www.cnblogs.com/yanbigfeg
本文版权归作者和博客园共有,欢迎转载,转载请标明出处。如果您觉得本篇博文对您有所收获,觉得小弟还算用心,请点击右下角的 [推荐],谢谢!