使用PDF.js渲染canvas实现预览pdf的效果示例


Posted in Javascript onApril 17, 2021

一、PDF.js的下载

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

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

使用PDF.js渲染canvas实现预览pdf的效果示例

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

二、使用PDF.js

1.vue使用

第一步安装:

npm install --save pdfjs-dist

第二步引入:

import PDFJS from 'pdfjs-dist'

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

export default {
 data () {
  return {
   pdfDoc: null,
   pageNum: 1,
   pageRendering: false,
   pageNumPending: null,
   scale: 0.9
  }
 },
 methods: {
  showPDF (url) {
   let _this = this
   PDFJS.getDocument(url).then(function (pdf) {
    _this.pdfDoc = pdf
    _this.renderPage(1)
   })
  },
  renderPage (num) {
   this.pageRendering = true
   let _this = this
   this.pdfDoc.getPage(num).then(function (page) {
    var viewport = page.getViewport(_this.scale)
    let canvas = document.getElementById('the-canvas')
    canvas.height = viewport.height
    canvas.width = viewport.width

    // Render PDF page into canvas context
    var renderContext = {
     canvasContext: canvas.getContext('2d'),
     viewport: viewport
    }
    var renderTask = page.render(renderContext)
  
    // Wait for rendering to finish
    renderTask.promise.then(function () {
     _this.pageRendering = false
     if (_this.pageNumPending !== null) {
      // New page rendering is pending
      this.renderPage(_this.pageNumPending)
      _this.pageNumPending = null
     }
    })
   })
  },
  queueRenderPage (num) {
   if (this.pageRendering) {
    this.pageNumPending = num
   } else {
    this.renderPage(num)
   }
  },
  onPrevPage () {
   if (this.pageNum <= 1) {
    return
   }
   this.pageNum--
   this.queueRenderPage(this.pageNum)
  },
  onNextPage () {
   if (this.pageNum >= this.pdfDoc.numPages) {
    return
   }
   this.pageNum++
   this.queueRenderPage(this.pageNum)
  }
 }
}

2.HTML(5)使用

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

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

使用PDF.js渲染canvas实现预览pdf的效果示例

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

引入如下代码:

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

第三步即可在js中使用。

① 引入单页的pdf:

var url = sessionStorage.sencondExperience_filePath;
pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
pdfjsLib.getDocument(url).then(function getPdfHelloWorld(pdf) {
	pdf.getPage(1).then(function getPageHelloWorld(page) {
		var scale = 1;
		var viewport = page.getViewport(scale);
		var canvas = document.getElementById('the-canvas');
		var context = canvas.getContext('2d');
		canvas.height = viewport.height;
		canvas.width = viewport.width;
		var renderContext = {
			canvasContext: context,
			viewport: viewport
		};
		page.render(renderContext);
	});
});

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

②引入多页的pdf:

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

html:

<canvas id="the-canvas01"></canvas>
<canvas id="the-canvas02"></canvas>
<canvas id="the-canvas03"></canvas>

js:

var url = sessionStorage.third_filePath;
pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
pdfjsLib.getDocument(url).then(function getPdfHelloWorld(pdf) {
	pdf.getPage(1).then(function getPageHelloWorld(page) {
		var scale = 1;
		var viewport = page.getViewport(scale);
		var canvas = document.getElementById('the-canvas01');
		var context = canvas.getContext('2d');
		canvas.height = viewport.height;
		canvas.width = viewport.width;
		var renderContext = {
			canvasContext: context,
			viewport: viewport
		};
		page.render(renderContext);
	});
	pdf.getPage(2).then(function getPageHelloWorld(page) {
		var scale = 1;
		var viewport = page.getViewport(scale);
		var canvas = document.getElementById('the-canvas02');
		var context = canvas.getContext('2d');
		canvas.height = viewport.height;
		canvas.width = viewport.width;
		var renderContext = {
			canvasContext: context,
			viewport: viewport
		};
		page.render(renderContext);
	});
	pdf.getPage(3).then(function getPageHelloWorld(page) {
		var scale = 1;
		var viewport = page.getViewport(scale);
		var canvas = document.getElementById('the-canvas03');
		var context = canvas.getContext('2d');
		canvas.height = viewport.height;
		canvas.width = viewport.width;
		var renderContext = {
			canvasContext: context,
			viewport: viewport
		};
		page.render(renderContext);
	});
});

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

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

html

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

js

//PDF转成图片
var url = sessionStorage.other_filePath;
pdfjsLib.workerSrc = 'PDF.js/build/pdf.worker.js';
//创建
function createPdfContainer(id, className) {
    var pdfContainer = document.getElementById('canvas');
    var canvasNew = document.createElement('canvas');
    $("canvas").on("click",function() {
		var url = sessionStorage.other_filePath;
		window.open(url);
    })
    canvasNew.id = id;
    canvasNew.className = className;
    pdfContainer.appendChild(canvasNew);
};

//渲染pdf
//建议给定pdf宽度
function renderPDF(pdf, i, id) {
    pdf.getPage(i).then(function (page) {

        var scale = 0.62;
        var viewport = page.getViewport(scale);

        //
        //  准备用于渲染的 canvas 元素
        //

        var canvas = document.getElementById(id);
        var context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = document.documentElement.clientWidth;

        //
        // 将 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) {
    pdfjsLib.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(url)

三、报错

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

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

在html中:

<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导致出错。错误代码如下:

for(const i in pdf.numPages){
	pdf.getPage(i).then(function getPageHelloWorld(page) {
		var scale = 1;
		var viewport = page.getViewport(scale);
		var id = i > 9 ? 'the-canvas' + i : 'the-canvas0' + i;
		var canvas = document.getElementById(id);
		var context = canvas.getContext('2d');
		canvas.height = viewport.height;
		canvas.width = viewport.width;
		var renderContext = {
			canvasContext: context,
			viewport: viewport
		};
		page.render(renderContext);
	});
}

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

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

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

 
Javascript 相关文章推荐
js arguments.callee的应用代码
May 07 Javascript
jQuery 源码分析笔记(7) Queue
Jun 19 Javascript
JQuery扩展插件Validate 5添加自定义验证方法
Sep 05 Javascript
JS中令人发指的valueOf方法介绍
Feb 22 Javascript
JavaScript 事件入门知识
Apr 13 Javascript
jQuery实现右侧显示可向左滑动展示的深色QQ客服效果代码
Oct 23 Javascript
使用vue.js制作分页组件
Jun 27 Javascript
微信小程序 template模板详解及实例
Feb 21 Javascript
View.post() 不靠谱的地方你知道多少
Aug 29 Javascript
jQuery实现参数自定义的文字跑马灯效果
Aug 15 jQuery
vue  elementUI 表单嵌套验证的实例代码
Nov 06 Javascript
Ant Design Vue 添加区分中英文的长度校验功能
Jan 21 Javascript
详解如何在Canvas中添加事件的方法
Apr 17 #Javascript
Canvas三种动态画圆实现方法说明(小结)
如何在CocosCreator里画个炫酷的雷达图
jquery插件实现图片悬浮
详解CocosCreator消息分发机制
Apr 16 #Javascript
CocosCreator入门教程之网络通信
Apr 16 #Javascript
JavaScript嵌入百度地图API的最详细方法
You might like
网页游戏开发入门教程二(游戏模式+系统)
2009/11/02 PHP
php smarty 二级分类代码和模版循环例子
2011/06/01 PHP
js和jquery批量绑定事件传参数一(新猪猪原创)
2010/06/23 Javascript
10个基于Jquery的幻灯片插件教程
2010/10/29 Javascript
了解一点js的Eval函数
2012/07/26 Javascript
在子窗口中关闭父窗口的一句代码
2013/10/21 Javascript
jquery.post用法关于type设置问题补充
2014/01/03 Javascript
JavaScript字符串对象substr方法入门实例(用于截取字符串)
2014/10/16 Javascript
JavaScript将XML转成JSON的方法
2015/03/12 Javascript
js实现简单的验证码
2015/12/25 Javascript
详解JavaScript对象序列化
2016/01/19 Javascript
php基于redis处理session的方法
2016/03/14 Javascript
vue中子组件向父组件传递数据的实例代码(实现加减功能)
2018/04/20 Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
2018/12/12 Javascript
vue之延时刷新实例
2019/11/14 Javascript
React学习之JSX与react事件实例分析
2020/01/06 Javascript
vue实现图片上传功能
2020/05/28 Javascript
[02:06]DOTA2肉山黑名单魔法终结者 敌法师中文配音鉴赏
2013/06/17 DOTA
[02:07]2018DOTA2亚洲邀请赛主赛事第三日五佳镜头 fy极限反杀
2018/04/06 DOTA
python利用beautifulSoup实现爬虫
2014/09/29 Python
Python找出9个连续的空闲端口
2016/02/01 Python
Python数据库的连接实现方法与注意事项
2016/02/27 Python
python format 格式化输出方法
2018/07/16 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
Python迭代器模块itertools使用原理解析
2019/12/11 Python
Python统计学一数据的概括性度量详解
2020/03/03 Python
HTML5 progress和meter控件_动力节点Java学院整理
2017/07/06 HTML / CSS
Furla官网:意大利著名的皮革品牌
2019/08/06 全球购物
销售顾问的岗位职责
2013/11/13 职场文书
干部行政关系介绍信
2014/01/17 职场文书
项目施工员岗位职责
2014/03/09 职场文书
关于环保的标语
2014/06/13 职场文书
党委班子剖析材料
2014/08/21 职场文书
毕业证丢失证明范本
2014/09/20 职场文书
python实现自定义日志的具体方法
2021/05/28 Python
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
2022/03/03 Python