经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
使用PDF.js渲染canvas实现预览pdf的效果示例
来源:jb51  时间:2021/4/19 8:39:26  对本文有异议

一、PDF.js的下载

从官网直接下载即可,地址:http://mozilla.github.io/pdf.js/getting_started/#download

建议下载稳定版本,如下图所示:

在这里插入图片描述

下载完成后将压缩包解压放在项目下,按照正常引入方式引入即可。

二、使用PDF.js

1.vue使用

第一步安装:

  1. npm install --save pdfjs-dist

第二步引入:

  1. import PDFJS from 'pdfjs-dist'

第三步就是在页面使用即可,下面演示export default中的代码:

  1. export default {
  2. data () {
  3. return {
  4. pdfDoc: null,
  5. pageNum: 1,
  6. pageRendering: false,
  7. pageNumPending: null,
  8. scale: 0.9
  9. }
  10. },
  11. methods: {
  12. showPDF (url) {
  13. let _this = this
  14. PDFJS.getDocument(url).then(function (pdf) {
  15. _this.pdfDoc = pdf
  16. _this.renderPage(1)
  17. })
  18. },
  19. renderPage (num) {
  20. this.pageRendering = true
  21. let _this = this
  22. this.pdfDoc.getPage(num).then(function (page) {
  23. var viewport = page.getViewport(_this.scale)
  24. let canvas = document.getElementById('the-canvas')
  25. canvas.height = viewport.height
  26. canvas.width = viewport.width
  27.  
  28. // Render PDF page into canvas context
  29. var renderContext = {
  30. canvasContext: canvas.getContext('2d'),
  31. viewport: viewport
  32. }
  33. var renderTask = page.render(renderContext)
  34. // Wait for rendering to finish
  35. renderTask.promise.then(function () {
  36. _this.pageRendering = false
  37. if (_this.pageNumPending !== null) {
  38. // New page rendering is pending
  39. this.renderPage(_this.pageNumPending)
  40. _this.pageNumPending = null
  41. }
  42. })
  43. })
  44. },
  45. queueRenderPage (num) {
  46. if (this.pageRendering) {
  47. this.pageNumPending = num
  48. } else {
  49. this.renderPage(num)
  50. }
  51. },
  52. onPrevPage () {
  53. if (this.pageNum <= 1) {
  54. return
  55. }
  56. this.pageNum--
  57. this.queueRenderPage(this.pageNum)
  58. },
  59. onNextPage () {
  60. if (this.pageNum >= this.pdfDoc.numPages) {
  61. return
  62. }
  63. this.pageNum++
  64. this.queueRenderPage(this.pageNum)
  65. }
  66. }
  67. }

2.HTML(5)使用

第一步正常下载后解压放入项目中;

第二步在项目的页面引入即可,项目结构如下图:

在这里插入图片描述

由于是公司项目,我将项目名遮住,大家自行取名即可,我在此处将PDF.js放入了js目录下,大家也可以直接放在项目的根目录下。

引入如下代码:

  1. <script type='text/javascript' src='js/PDF.js/build/pdf.js'></script>

第三步即可在js中使用。

① 引入单页的pdf:

  1. var url = sessionStorage.sencondExperience_filePath;
  2. pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
  3. pdfjsLib.getDocument(url).then(function getPdfHelloWorld(pdf) {
  4. pdf.getPage(1).then(function getPageHelloWorld(page) {
  5. var scale = 1;
  6. var viewport = page.getViewport(scale);
  7. var canvas = document.getElementById('the-canvas');
  8. var context = canvas.getContext('2d');
  9. canvas.height = viewport.height;
  10. canvas.width = viewport.width;
  11. var renderContext = {
  12. canvasContext: context,
  13. viewport: viewport
  14. };
  15. page.render(renderContext);
  16. });
  17. });

需要注意的是pdfjsLib.workerSrc中,如果换成是PDFJS.workerSrc会报错:PDFJS is notdefined。有博客说在其之前加上PDFJS.disableWorker = true;会避免出错,但我尝试了错误依然存在。使用pdfjsLib.workerSrc不会出错!!!

②引入多页的pdf:

方法一:在html中设置好pdf页数对应的canvas,然后使用js一页一页的去渲染canvas。

html:

  1. <canvas id="the-canvas01"></canvas>
  2. <canvas id="the-canvas02"></canvas>
  3. <canvas id="the-canvas03"></canvas>

js:

  1. var url = sessionStorage.third_filePath;
  2. pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
  3. pdfjsLib.getDocument(url).then(function getPdfHelloWorld(pdf) {
  4. pdf.getPage(1).then(function getPageHelloWorld(page) {
  5. var scale = 1;
  6. var viewport = page.getViewport(scale);
  7. var canvas = document.getElementById('the-canvas01');
  8. var context = canvas.getContext('2d');
  9. canvas.height = viewport.height;
  10. canvas.width = viewport.width;
  11. var renderContext = {
  12. canvasContext: context,
  13. viewport: viewport
  14. };
  15. page.render(renderContext);
  16. });
  17. pdf.getPage(2).then(function getPageHelloWorld(page) {
  18. var scale = 1;
  19. var viewport = page.getViewport(scale);
  20. var canvas = document.getElementById('the-canvas02');
  21. var context = canvas.getContext('2d');
  22. canvas.height = viewport.height;
  23. canvas.width = viewport.width;
  24. var renderContext = {
  25. canvasContext: context,
  26. viewport: viewport
  27. };
  28. page.render(renderContext);
  29. });
  30. pdf.getPage(3).then(function getPageHelloWorld(page) {
  31. var scale = 1;
  32. var viewport = page.getViewport(scale);
  33. var canvas = document.getElementById('the-canvas03');
  34. var context = canvas.getContext('2d');
  35. canvas.height = viewport.height;
  36. canvas.width = viewport.width;
  37. var renderContext = {
  38. canvasContext: context,
  39. viewport: viewport
  40. };
  41. page.render(renderContext);
  42. });
  43. });

可想而知,这种方法对于页面较少的pdfHIA比较合适,但是若是页数很多或者是不知道pdf的页数的情况,这种方法显然不适合了,由此推荐方法二。

方法二:只需要定义好在需要渲染的位置,再根据pdf的页数去动态渲染canvas。

html

  1. < div id="canvas"></ div>

js

  1. //PDF转成图片
  2. var url = sessionStorage.other_filePath;
  3. pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
  4. //创建
  5. function createPdfContainer(id, className) {
  6. var pdfContainer = document.getElementById('canvas');
  7. var canvasNew = document.createElement('canvas');
  8. $("canvas").on("click",function() {
  9. var url = sessionStorage.other_filePath;
  10. window.open(url);
  11. })
  12. canvasNew.id = id;
  13. canvasNew.className = className;
  14. pdfContainer.appendChild(canvasNew);
  15. };
  16.  
  17. //渲染pdf
  18. //建议给定pdf宽度
  19. function renderPDF(pdf, i, id) {
  20. pdf.getPage(i).then(function (page) {
  21.  
  22. var scale = 0.62;
  23. var viewport = page.getViewport(scale);
  24.  
  25. //
  26. // 准备用于渲染的 canvas 元素
  27. //
  28.  
  29. var canvas = document.getElementById(id);
  30. var context = canvas.getContext('2d');
  31. canvas.height = viewport.height;
  32. canvas.width = document.documentElement.clientWidth;
  33.  
  34. //
  35. // 将 PDF 页面渲染到 canvas 上下文中
  36. //
  37. var renderContext = {
  38. canvasContext: context,
  39. viewport: viewport
  40. };
  41. page.render(renderContext);
  42. });
  43. };
  44. //创建和pdf页数等同的canvas数
  45. function createSeriesCanvas(num, template) {
  46. var id = '';
  47. for (var j = 1; j <= num; j++) {
  48. id = template + j;
  49. createPdfContainer(id, 'pdfClass');
  50. }
  51. }
  52. //读取pdf文件,并加载到页面中
  53. function loadPDF(fileURL) {
  54. pdfjsLib.getDocument(fileURL).then(function (pdf) {
  55. //用 promise 获取页面
  56. var id = '';
  57. var idTemplate = 'cw-pdf-';
  58. var pageNum = pdf.numPages;
  59. //根据页码创建画布
  60. createSeriesCanvas(pageNum, idTemplate);
  61. //将pdf渲染到画布上去
  62. for (var i = 1; i <= pageNum; i++) {
  63. id = idTemplate + i;
  64. renderPDF(pdf, i, id);
  65. }
  66. });
  67. }
  68. loadPDF(url)

三、报错

1.Uncaught TypeError: Cannot read property ‘getContext’ of null

这个错误是因为在html中需要先写好<canvas>标签,定义好id,不能使用div或其他标签。

在html中:

  1. <canvas id="my-canvas"></canvas>

2.Uncaught (in promise) UnknownErrorException {name: “UnknownErrorException”, message: “Failed to fetch”, details: “UnknownErrorException: Failed to fetch”}

这个意思是未能捕获未知错误。我在此处出错的原因主要是后台给的pdf路径有问题导致的,换一个正确的即可~~

3.Uncaught (in promise) InvalidPDFException {name: “InvalidPDFException”, message: “Invalid PDF structure”}

这个意思是说无效的PDF格式的结构,其实就是代码中渲染pdf时的结构出现错误导致的,我是因为直接对pdf的页数:pdf.numPages循环,再去
渲染在canvas导致出错。错误代码如下:

  1. for(const i in pdf.numPages){
  2. pdf.getPage(i).then(function getPageHelloWorld(page) {
  3. var scale = 1;
  4. var viewport = page.getViewport(scale);
  5. var id = i > 9 ? 'the-canvas' + i : 'the-canvas0' + i;
  6. var canvas = document.getElementById(id);
  7. var context = canvas.getContext('2d');
  8. canvas.height = viewport.height;
  9. canvas.width = viewport.width;
  10. var renderContext = {
  11. canvasContext: context,
  12. viewport: viewport
  13. };
  14. page.render(renderContext);
  15. });
  16. }

此时将id打印才明白所有id都为 the-canvas15,出现这个错误主要还是js功底不够扎实导致......所以不能这样简单的循环渲染,正确的解决
方法请看上面的讲解!!!

由此关于PDF.js的使用总结就到这了,有什么问题请留言撒~~

到此这篇关于使用PDF.js渲染canvas实现预览pdf的效果示例的文章就介绍到这了,更多相关PDF.js渲染canvas内容请搜索w3xue以前的文章或继续浏览下面的相关文章,希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号