功能描述:实现pdf的预览,以及一些简单的功能:翻页,下载,放大,缩小
详细使用过程
1.下载插件
npm install --save pdfjs-dist@2.0.943
最好指定一下这个版本,不要用最新的,容易出错
2.上代码
新建一个vue文件,如viewPDF.vue
<template>
<div class="pdf-wrap">
<div class="contral">
<div class="changePage">
<svg-icon @click="prev" class="icon" icon-class="arrow-up" style="width: 16px; height: 16px"></svg-icon>
<svg-icon @click="prev" class="icon" icon-class="arrow-down" style="width: 16px; height: 16px"></svg-icon>
<span class="page">{{pageNum}} / {{pageCount}}页</span>
</div>
<div class="title">来瞧瞧pdf</div>
<div class="func">
<span>下载</span>
</div>
</div>
<div class="content" id="pdfContent"></div>
<div class="reading">
<a-button>已阅读</a-button>
</div>
</div>
</template>
<script>
import * from PDF from 'pdfjs-dist'
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'
PDF.globalWorkerOptions.workerSrc = pdfjsWorker
PDF.disabledWorker = true
export default{
props: {
filePath: String,
fileName: String
},
data(){
return {
pdfDoc: null, // pdf读取的页面信息
pageNum: 0, // 当前页数
pageCount: 0, // 总页数
pageRendering: false, // 当前页面是否渲染
pageNumPending: null, // 将要进行渲染的页面页数
time: 20, // 阅读时间
}
},
methods: {
loadFile(filePath){
PDF.getDocument(filePath).then(pdf => {
this.pageNum = 1
this.pdfDoc = pdf
this.pageCount = pdf.numPages
this.$nextTick(() => {
this.renderPage(this.pageNum)
})
})
},
renderPage(num){
this.pdfDoc.getPage(num).then(page => {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
let dpr = window.devicePixelRatio || 1 // 设备像素比,用来解决canvas的清晰度问题
let bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.BackingStorePixelRatio // 浏览器在渲染canvas之前会用几个像素比来存贮画布
let ratio = dpr / bsr
let viewport = page.getViewPort(1)
canvas.width = viewport.width * ratio
canvas.height = viewport.height * ratio
ctx.fillStyle = 'rgba(255,255,255,0)'
canvas.style.width = viewport.width + 'px'
canvas.style.height = viewport.height + 'px'
let renderContext = {
canvasContext: ctx,
viewport: viewport
}
page.render(renderContext).promise.then(() => {
ctx.fillRect(0,0, canvas.width, canvas.height) // fillRect绘制填充的矩形(x,y,width,height),默认填充黑色,结合上面的ctx.fillStyle设置填充白色
// 动态绘制canvas,如果存在canvas,则销毁,重新渲染
const domCanvas = document.querySelector('canvas')
const domPdfContext = document.querySelector('#pdfContent')
if(domCanvas) domPdfContext.removeChild(domCanvas)
domPdfContext.appendChild(domCanvas)
this.pageRendering = false
// 如果有未渲染的下一页,则渲染下一页
if(this.pageNumPending != null){
this.renderPage(this.pageNumPending)
this.pageNumPending = null
}
})
})
},
// 上一页
prev(){
if(this.pageNum <= 1){
return
}
this.pageNum--
this.waitRenderPage(this.pageNum)
},
// 下一页
next(){
if(this.pageNum >= this.pageCount){
return
}
this.pageNum++
this.waitRenderPage(this.pageNum)
},
// 改变渲染页面
waitRenderPage(num){
const n = Number(num)
if(this.pageNumPending){
this.pageNumPending = n
}else {
this.renderPage(n)
}
},
// 下载文件
downLoad(){
let a = document.createElement('a')
a.downLoad = this.fileName
a.href = this.filePath
a.style.display = 'none'
document.body.appendChild(a)
a.click()
document.removeChild(a)
},
// 放大和缩小有时间再补充吧
}
}
</script>
<style lang="less" scoped>
.pdf-wrap{
width: 1200px;
.contral{
height: 64px;
display: flex;
line-height: 64px;
font-size: 14px;
color: #0a0c10;
font-weight: 400;
border: 1px solid rgba(228, 230, 234, 1);
.changePage{
width: 33.3%;
text-align: right;
.icon{
margin-right: 16px;
}
}
.title{
width: 33.3%;
font-size: 20px;
color: #0a0c10;
font-weight: 500;
text-align: center;
}
.func{
width: 33.4%;
text-align: right;
padding-right: 96px;
}
}
.tontent{
height: calc(100vh - 100px);
background-color: #f1f2f6;
overflow-y: auto;
}
.reading{
text-align: center;
margin-top: 10px;
}
}
</style>
好了,重点就结束了,可以在需要的地方进行展示,调用这个组件的时候注意两点:
- 父组件传入自定义参数fileName和filePath哦;
- 不要忘记父组件要调用子组件的方法loadFile方法
tip: 代码里面有图片,分别是上一页和下一页,不重要,换掉他!
有关canvas的绘制,其中devicePixelRatio和webkitBackingStorePixelRatio,也想要记录一下,期待下一篇文章吧
以上内容也是根据需要参考借鉴了很多大佬的,感谢!