Vue实现pdf在线预览功能的示例代码
作者:cypking
这篇文章主要为大家详细介绍了如何使用Vue实现pdf在线预览功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
一、文件预览
1、安装依赖包
这里安装了disjs-dist@2.16版本,安装过程中报错缺少worker-loader
npm i pdfjs-dist@2.16.105 worker-loader@3.0.8
2、模板部分
<template> <div id="pdf-view"> <canvas v-for="page in pdfPages" :key="page" :id="pdfCanvas" /> <div id="text-view"></div> </div> </template>
3、js部分(核心)
核心代码如下:
- 利用 PDF.getDocument获取pdf基础数据
- 通过canvas将pdf渲染到canvas画布上
import * as pdfjsViewer from "pdfjs-dist/web/pdf_viewer.js"; import "pdfjs-dist/web/pdf_viewer.css"; import * as PDF from "pdfjs-dist/webpack"; export default { name: "", components: {}, data() { return { pdfPages: 1, pdfPath: "http://localhost:8080/qfnext.pdf", // 总页数 pdfPages: 1, // 页面缩放 pdfScale: 1, pdfDoc: null, }; }, mounted() { this.loadFile(this.pdfPath); }, methods: { loadFile(url) { PDF.getDocument({ url, cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/", cMapPacked: true, }).promise.then((pdf) => { this.pdfDoc = pdf; // 获取pdf文件总页数 this.pdfPages = pdf.numPages; this.$nextTick(() => { this.renderPage(1); // 从第一页开始渲染 }); }); }, renderPage(num) { this.pdfDoc.getPage(num).then((page) => { const canvas = document.getElementById(`pdfCanvas`); const ctx = canvas.getContext("2d"); const viewport = page.getViewport({ scale: this.pdfScale }); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: ctx, viewport, }; page.render(renderContext); }); }, }, };
可能出现的问题:
(1) 页面文字可选中,但文本不可见
通过测试发现,将 pdfjs-dist/web/pdf_viewer.css 路径下的 color 属性注释后可显示文本。
.textLayer span, .textLayer br { /* color: transparent; */ position: absolute; white-space: pre; cursor: text; transform-origin: 0% 0%; }
pdf多页面处理
模板处理id作为唯一标识
<canvas v-for="page in pdfPages" :key="page" :id="`page-${page}`" />
修改canvas渲染逻辑,主要通过递归的方式逐一渲染
renderPage(num) { this.pdfDoc.getPage(num).then((page) => { const canvas = document.getElementById(`page-${num}`); const ctx = canvas.getContext("2d"); const viewport = page.getViewport({ scale: this.pdfScale }); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: ctx, viewport, }; page.render(renderContext); if (num < this.pdfPages) { this.renderPage(num + 1); } }); },
二、文本选中与弹窗(核心代码)
Promise.all([getTextContentPromise, renderPagePromise]) .then(([textContent]) => { const textLayerDiv = document.createElement("div"); // 注意:此处不要修改该元素的class名称,该元素的样式通过外部导入,名称是固定的 textLayerDiv.setAttribute("class", "textLayer"); // 设置容器样式 textLayerDiv.setAttribute( "style", ` z-index: 1; opacity: .2; // background-color:#fff; // transform: scale(1.1); width: 100%, height: 100%, `, ); // 设置容器的位置和宽高 textLayerDiv.style.left = canvas.offsetLeft + "px"; textLayerDiv.style.top = canvas.offsetTop + "px"; textLayerDiv.style.height = canvas.offsetHeight + "px"; textLayerDiv.style.width = canvas.offsetWidth + "px"; const textView = document.querySelector("#text-view"); textView.appendChild(textLayerDiv); const textLayer = new TextLayerBuilder({ // container: , textLayerDiv: textLayerDiv, pageIndex: page.pageIndex, viewport: viewport, eventBus, // textDivs: [] }); textLayer.setTextContent(textContent); textLayer.render(); // 当选择文本后鼠标取消点击时触发 textLayerDiv.addEventListener("mouseup", () => { // // 隐藏文本层 // textLayerDiv.style.display = 'none'; // 是否选择了文本 const isTextSelected = window.getSelection().toString().trim() !== ""; if (isTextSelected) { //选择的文本内容 const selectedText = window.getSelection().toString(); console.log("Selected text:", selectedText); if (selectedText) { alert(selectedText); } } }); }) .catch((error) => { console.error("Error rendering page:", error); });
三、完整代码如下
<template> <div id="pdf-view"> <canvas v-for="page in pdfPages" :key="page" :id="`page-${page}`" /> <div id="text-view"></div> </div> </template> <script> import * as pdfjsViewer from "pdfjs-dist/web/pdf_viewer.js"; import "pdfjs-dist/web/pdf_viewer.css"; import * as PDF from "pdfjs-dist/webpack"; // import { getDocument } from 'pdfjs-dist/webpack'; import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer.js"; const pdfjsWorker = import("pdfjs-dist/build/pdf.worker.entry"); PDF.GlobalWorkerOptions.workerSrc = pdfjsWorker; const eventBus = new pdfjsViewer.EventBus(); export default { name: "", components: {}, data() { return { pdfPages: 1, pdfPath: "http://localhost:8080/qfnext.pdf", // 总页数 pdfPages: 1, // 页面缩放 pdfScale: 1, pdfDoc: null, }; }, mounted() { this.loadFile(this.pdfPath); }, methods: { loadFile(url) { PDF.getDocument({ url, cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/", cMapPacked: true, }).promise.then((pdf) => { this.pdfDoc = pdf; // 获取pdf文件总页数 this.pdfPages = pdf.numPages; this.$nextTick(() => { this.renderPage(1); // 从第一页开始渲染 }); }); }, renderPage(num) { this.pdfDoc.getPage(num).then((page) => { const canvas = document.getElementById(`page-${num}`); const ctx = canvas.getContext("2d"); const viewport = page.getViewport({ scale: this.pdfScale }); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: ctx, viewport, }; // 获取文本内容和渲染页面的 Promise const getTextContentPromise = page.getTextContent(); const renderPagePromise = page.render(renderContext); if (num < this.pdfPages) { this.renderPage(num + 1); } Promise.all([getTextContentPromise, renderPagePromise]) .then(([textContent]) => { const textLayerDiv = document.createElement("div"); // 注意:此处不要修改该元素的class名称,该元素的样式通过外部导入,名称是固定的 textLayerDiv.setAttribute("class", "textLayer"); // 设置容器样式 textLayerDiv.setAttribute( "style", ` z-index: 1; opacity: .2; // background-color:#fff; // transform: scale(1.1); width: 100%, height: 100%, `, ); // 设置容器的位置和宽高 textLayerDiv.style.left = canvas.offsetLeft + "px"; textLayerDiv.style.top = canvas.offsetTop + "px"; textLayerDiv.style.height = canvas.offsetHeight + "px"; textLayerDiv.style.width = canvas.offsetWidth + "px"; const textView = document.querySelector("#text-view"); textView.appendChild(textLayerDiv); const textLayer = new TextLayerBuilder({ // container: , textLayerDiv: textLayerDiv, pageIndex: page.pageIndex, viewport: viewport, eventBus, // textDivs: [] }); textLayer.setTextContent(textContent); textLayer.render(); // 当选择文本后鼠标取消点击时触发 textLayerDiv.addEventListener("mouseup", () => { // // 隐藏文本层 // textLayerDiv.style.display = 'none'; // 是否选择了文本 const isTextSelected = window.getSelection().toString().trim() !== ""; if (isTextSelected) { //选择的文本内容 const selectedText = window.getSelection().toString(); console.log("Selected text:", selectedText); if (selectedText) { alert(selectedText); } } }); }) .catch((error) => { console.error("Error rendering page:", error); }); }); }, }, }; </script> <style lang="scss" scoped> .pdf-con { border: 2px solid #ccc; width: 80%; margin: auto; height: 800px; overflow: auto; // display: none; } </style>
到此这篇关于Vue实现pdf在线预览功能的示例代码的文章就介绍到这了,更多相关Vue pdf在线预览内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!