工作笔记三——使用pdf.js实现pdf文件的在线预览
最近做移动项目(H5)时遇到一个需求,就是在线预览pdf文件。其实本来使用window.open()就可以实现了,但是这个API在IOS上是正常的打开Safari浏览器进行预览,在安卓上打开是则是下载预览,客户不满意;而且在将该应用嵌入到钉钉微应用时,这个API在安卓设备上根本不起效果。于是在网上找到了这个插件,去官网摘了个例子,并且结合移动端的上下左右滑动滑动翻页做了个例子,完美解决。以下是详细代码。注释都在代码中。
<html>
<head>
<meta charset="UTF-8">
<title>pdf在线预览</title>
<script src="js/pdf.js" type="text/javascript"></script>
<style>
button {
display: flex;
justify-content: center;
align-items: center;
background-color: lightseagreen;
border: 1px solid transparent;
border-radius: 5px;
height: 30px;
width: 70px;
}
.header-bar {
background-color: cornflowerblue;
height: 5%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 2em;
}
.pdf-container {
background-color: gainsboro;
display: flex;
justify-content: center;
align-items: center;
height: 95%
}
canvas{
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="header-bar">
<span>当前第 <span id="page_num"></span> 页 共<span id="page_count"></span>页</span>
</div>
<div class="pdf-container">
<canvas id="the-canvas"></canvas>
</div>
</body>
<script type="text/javascript">
var url = 'test-js.pdf';
// workerSrc的路径
PDFJS.workerSrc = 'js/pdf.worker.js';
var pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 1,////设置pdf文本显示区域的缩放级别
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
/**
* 渲染对应的文档页码,并且调整canvas大小,渲染界面
* @param num 页码.
*/
function renderPage(num) {
pageRendering = true;
// 通过promise来获取
pdfDoc.getPage(num).then(function (page) {
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
//将PDF文件渲染进canvas中
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
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 = num;
}
/**
* 如果有另一个页面pdf页正在渲染,那么先等这个pdf页渲染完再渲染。否则立即渲染传进来的页码。
*/
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}
/**
* 上一页
*/
function onPrevPage() {
if (pageNum <= 1) {
return;
}
pageNum--;
queueRenderPage(pageNum);
}
/**
* 下一页
*/
function onNextPage() {
if (pageNum >= pdfDoc.numPages) {
return;
}
pageNum++;
queueRenderPage(pageNum);
}
/**
* 异步的下载pdf文件
*/
PDFJS.getDocument(url).then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
document.getElementById('page_count').textContent = pdfDoc.numPages;
// 下载完以后初始化渲染第一页
renderPage(pageNum);
});
function _touch() {
var startx;//让startx在touch事件函数里是全局性变量。
var endx;
var el = document.getElementsByTagName("body")[0];
function cons() { //独立封装这个事件可以保证执行顺序,从而能够访问得到应该访问的数据。
var l = Math.abs(startx - endx);
var h = Math.abs(starty - endy);
if (l > h) {
// x事件
if (startx > endx) {
onNextPage();
} else if (startx < endx) {
onPrevPage();
}
} else {
// y事件
if (starty > endy) {
onNextPage();
} else if (starty < endy) {
onPrevPage();
}
}
}
el.addEventListener('touchstart', function (e) {
var touch = e.changedTouches;
startx = touch[0].clientX;
starty = touch[0].clientY;
});
el.addEventListener('touchend', function (e) {
var touch = e.changedTouches;
endx = touch[0].clientX;
endy = touch[0].clientY;
cons(); //startx endx 的数据收集应该放在touchend事件后执行,而不是放在touchstart事件里执行,这样才能访问到touchstart和touchend这2个事件产生的startx和endx数据。另外startx和endx在_touch事件函数里是全局性的,所以在此函数中都可以访问得到,所以只需要注意事件执行的先后顺序即可。
});
}
_touch();
</script>
</html>
demo演示效果:
demo地址:
github: https://github.com/JerryYuanJ/demos/tree/master/01-pdf-online-viewer
csdn:http://download.csdn.net/download/qq_25324335/10192172
github上版本的对结构做了一点修改。欢迎star。