vue + pdf.js
今天接到一个需求,做在线学习,需要展示pdf,并且在pdf阅读滚动条拖动到底部时候学习完成,分析一下这个需求,也就是2点
- 前端展示pdf
- pdf滚动条拖动到底部时候触发一个函数
二话不说,直接pdf怼进一个iframe标签的src属性,直接展示成功
代码:
<template>
<div id="test">
<iframe id="iframe" src="http://record.buhuidadaima.com/bb.pdf" width="800px" height="700px;"></iframe>
</div>
</template>
效果:
然后接下来,只要获取iframe的高度,然后pdf内容高度,已经pdf距离iframe顶部的高度,即可计算的出pdf什么时候触底
触底公式: pdf内容高度 = pdf距离iframe顶部的高度 + iframe的高度
搞清楚公式我们就要来获取我们的目标值了
- ifame的高度: 这个是自己写死的,这个直接获取即可
- pdf的内容高度,因为这个pdf是放在iframe框架里面的,所以直接
docuemnt.getElementById('')
是拿不到的,我们首先要那个ifrme框架整个对象,再来获取pdf元素高度,获取iframe框架对象有挺多种方法,我这里就贴出我的获取方式:window.frames[0]
拿到iframe框架对象, ok
window.frames[0].document
拿到iframe框架里面的文档对象 ok
window.frames[0].document.getElementById('pdf')
这步出事了
你会发现第二步获取完之后,拿到一个document之后里面没有你需要得元素,元素没有pdf得高度,距离顶部距离也永远都是0,这样就没有办法做计算了,走不通了。
这个时候我们就要搬出我们主角pdf.js来使用了,
- 先去下载pdf.js的压缩文件,选择个稳定版的下载: pdf.js下载地址
- 下载后解压开,能看到两个文件夹,
- 打开web文件夹,里面有一个
viewer.html
,点击打开就是个demo的pdf展示(然后你会发现打开什么都没有,没错就是跨域的)
啥都没有
- 这个时候让把刚刚解压开的文件放到服务器项目的文件夹里面,然后再访问
viewer.html
(前端不会弄叫后端放上去服务器,给个地址访问),访问服务器上面就可以看到demo了
- 然后我们要pdf.js来展示后端返给我们pdf,看代码:
<template>
<div id="test">
<!--src就是通过第4步访问服务器上面的demo地址,后面拼接?file=后端返回的pdf文件路径 -->
<iframe id="iframe" src="http://record.buhuidadaima.com/web/viewer.html?file=http://record.buhuidadaima.com/bb.pdf" width="800px" height="1100px;"></iframe>
</div>
</template>
- 已经可以展示pdf了,然后就到我们获取各种高度然后计算获取触底的时候,再看代码:
// 获取paf内容元素,这个重点,pdf.js加载出来的pdf多了这个元素,id就是viewerContainer
let page = window.frames[0].document.querySelector('#viewerContainer');
// 获取paf内容元素高度
let pageHeight = page.scrollHeight;
// iframe框架高度,注意这个是pdf工具栏的高度,实际自己页面可能还有别的div,会影响触底的计算
let iframeHeight = document.querySelector('#iframe').scrollHeight;;
// 获取pdf工具栏的高度
let tabHeight = window.frames[0].document.querySelector('#toolbarViewerRight').scrollHeight;
// 监听pdf滚动
page.onscroll = () => {
// 获取页面到顶部的高度,有了元素也就可以获取到元素到顶部的距离
let pageScorllTop = window.frames[0].document.querySelector('#viewerContainer').scrollTop;
// 判断触底
if(pageHeight - pageScorllTop + tabHeight === iframeHeight) {
console.log('完成pdf了,可以提交进度')
}
}