背景
公司需要前端在pdf上进行圈选区域,把区域给后端,然后识别文字的功能。
第一想法就是使用画布来实现。
在vue中使用pdf.js
1、安装
注意:一定要安装这个版本,新版本会错,很坑。。。
npm i pdfjs-dist@2.4.456 -D
2、使用、引入
- html
<canvas
style="border: solid 1px red"
v-for="page in pdf_pages" :id="'the-canvas'+page" :key="page">
</canvas>
- js
//引入pdf.js
import PDFJS from 'pdfjs-dist'
import workerSrc from 'pdfjs-dist/build/pdf.worker.entry'
export default {
data() {
return {
pdf_page: 0//pdf页数
}
},
methods: {
loadTestCanvas() {
const url = '/static/SE_BOOKING_GEN_SHAASCAVAN1000069.pdf' //pdf地址
let loadingTask = PDFJS.getDocument(url) //url的方式,下面介绍base64方式
loadingTask.promise
.then((pdf) => {
this.pdfDoc = pdf
this.pdf_pages = this.pdfDoc.numPages
this.$nextTick(() => {
//这边pdf就一页,默认为1页
this._renderPage(1)
})
})
},
_renderPage(num) { //渲染pdf页
const that = this
this.pdfDoc.getPage(num)
.then((page) => {
let canvas = document.getElementById('the-canvas' + num)
let ctx = canvas.getContext('2d')
let dpr = window.devicePixelRatio || 1
let bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1
let ratio = dpr / bsr
let viewport = page.getViewport({scale: 1}) //缩放默认为1
console.log(85, page)
canvas.width = viewport.width * ratio
canvas.height = viewport.height * ratio
canvas.style.width = viewport.width + 'px'
that.pdf_div_width = viewport.width + 'px'
canvas.style.height = viewport.height + 'px'
ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
let renderContext = {
canvasContext: ctx,
viewport: viewport
}
page.render(renderContext)
if (this.pdf_pages > num) {
this._renderPage(num + 1)
}
})
},
}
}
补充
1、利用base64展示
假如后端给的是base64,我们可以这么展示, base64转为atob
let loadingTask = PDFJS.getDocument({data: window.atob(this.pdfBase)})
2、url上加token
url = url+"?token=xxxxxxxxxxxxxxxxxx\
3、 二进制流
// data为后端传输
const blob = new Blob([data], {
type: 'application/pdf'
});
this.url = window.URL.createObjectURL(blob);