如何在PDF.JS中启用Annotations (替换pdf文本域的内容)
参考链接:https://usefulangle.com/post/94/javascript-pdfjs-enable-annotation-layer
1、添加一个<div>元素来保存注释层
<div id="annotation-layer"></div>
这个div将保存PDF页面的注释数据。PDF将在canvas中呈现。
<canvas id="pdf-canvas"></canvas> <div id="annotation-layer"></div>
2、为注释层添加CSS
#annotation-layer { position: absolute; section { position: absolute; display: flex !important; align-items: center !important; div { white-space: pre; color: black; font-size: 12px !important; line-height: 1 !important; } } }
3、获取PDF注释
在canvas中呈现PDF之后,您需要获得页面的注释数据,然后在注释层元素中呈现该数据。
方法getAnnotations()返回一个Promise,该Promise解析后返回页面的注释数据。render()将呈现注释层div中的数据。
完整代码:
<template> <div class="pdf-preview-container"> <div v-for="page in docPages" :key="page" ref="container" class="page-container" :style="{ height: `${pageHeight}px`, }" > <canvas v-if="renderList.includes(page)" id="pdf-canvas"> </canvas> <div id="annotation-layer"></div> </div> </div> </template> <script> const pdfJS = require('pdfjs-dist/build/pdf') const pdfjsWorker = require('pdfjs-dist/build/pdf.worker.entry') pdfJS.GlobalWorkerOptions.workerSrc = pdfjsWorker export default { props: { url: { type: String, required: true, }, data: { type: Object, default: () => {}, }, customScroll: { type: Boolean, default: false, }, offsetHeight: { type: Number, default: 0, }, }, data() { return { doc: null, docPages: 0, currentPage: 0, pageHeight: 0, renderList: [], } }, watch: { url: { immediate: true, handler() { this.getPDFFile() }, }, }, mounted() { if (!this.customScroll) { document.addEventListener('scroll', this.scroll) } }, beforeDestroy() { document.removeEventListener('scroll', this.scroll) }, methods: { async getPDFFile() { if (!this.url) return this.currentPage = 0 const pdf = await pdfJS.getDocument(this.url) this.doc = pdf this.docPages = pdf._pdfInfo.numPages this.$emit('getDocPages', this.docPages) this.$nextTick(() => { this.docPages && this.scrollToPage(1) }) }, scrollToPage(pageNo) { if (this.currentPage === pageNo) return this.currentPage = pageNo const list = [] for (let page = pageNo; page <= this.docPages; page++) { list.push(page) } this.$nextTick(() => { this.renderList = list this.renderList.forEach(page => { this.renderPage(page) }) }) }, // 渲染page async renderPage(pageNo) { const page = await this.doc.getPage(pageNo) const container = this.$refs.container[pageNo - 1] if (!container) return const canvas = container.querySelector('#pdf-canvas') const annotationLayer = container.querySelector('#annotation-layer') if (!canvas || canvas.__rendered) return const ctx = canvas.getContext('2d') const dpr = window.devicePixelRatio || 1 const bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1 const ratio = dpr / bsr const rect = container.getBoundingClientRect() const viewport = page.getViewport({ scale: 1 }) const width = rect.width const height = (width / viewport.width) * viewport.height canvas.style.width = `${width}px` canvas.style.height = `${height}px` this.pageHeight = height canvas.height = height * ratio canvas.width = width * ratio ctx.setTransform(ratio, 0, 0, ratio, 0, 0) const scale = width / viewport.width const renderContext = { canvasContext: ctx, viewport: page.getViewport({ scale }), } page.render(renderContext) canvas.__rendered = true const annotations = await page.getAnnotations() // console.log(pageNo, annotations) for (const annotation of annotations) { if (this.data[annotation.fieldName]) { annotation.fieldValue = this.data[annotation.fieldName] } } annotationLayer.style.width = `${width}px` annotationLayer.style.height = `${height}px` annotationLayer.style.left = `${canvas.offsetLeft}px` annotationLayer.style.top = `${canvas.offsetTop}px` // Render the annotation layer pdfJS.AnnotationLayer.render({ viewport: viewport.clone({ dontFlip: true, scale }), div: annotationLayer, annotations, page, }) }, scroll() { this.checkRender(document.documentElement) }, checkRender(el) { if (!this.pageHeight) return let scrollTop = el.scrollTop if (el === document.documentElement) { scrollTop = el.scrollTop || window.pageYOffset || document.body.scrollTop } let page = Math.floor((scrollTop - this.offsetHeight) / this.pageHeight) page = Math.max(page, 1) page = Math.min(page, this.docPages) this.scrollToPage(page) }, }, } </script> <style lang="scss"> #annotation-layer { position: absolute; section { position: absolute; display: flex !important; align-items: center !important; div { white-space: pre; color: black; font-size: 12px !important; line-height: 1 !important; } } } </style>
这里想要吐槽一下pdfjs的文档真是太不完善了,这个还是我研究了好几天源码才发现的功能。希望pdfjs能够把文档完善一下,要不用起来太不方便了o(╥﹏╥)o