Vue實現(xiàn)pdf在線預覽功能的示例代碼
更新時間:2025年03月07日 10:32:24 作者:cypking
這篇文章主要為大家詳細介紹了如何使用Vue實現(xiàn)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基礎數(shù)據(jù)
- 通過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",
// 總頁數(shù)
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文件總頁數(shù)
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);
});
},
},
};可能出現(xiàn)的問題:
(1) 頁面文字可選中,但文本不可見
通過測試發(fā)現(xiàn),將 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();
// 當選擇文本后鼠標取消點擊時觸發(fā)
textLayerDiv.addEventListener("mouseup", () => {
// // 隱藏文本層
// textLayerDiv.style.display = 'none';
// 是否選擇了文本
const isTextSelected =
window.getSelection().toString().trim() !== "";
if (isTextSelected) {
//選擇的文本內(nèi)容
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",
// 總頁數(shù)
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文件總頁數(shù)
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,
};
// 獲取文本內(nèi)容和渲染頁面的 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();
// 當選擇文本后鼠標取消點擊時觸發(fā)
textLayerDiv.addEventListener("mouseup", () => {
// // 隱藏文本層
// textLayerDiv.style.display = 'none';
// 是否選擇了文本
const isTextSelected =
window.getSelection().toString().trim() !== "";
if (isTextSelected) {
//選擇的文本內(nèi)容
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實現(xiàn)pdf在線預覽功能的示例代碼的文章就介紹到這了,更多相關Vue pdf在線預覽內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue前臺顯示500和405錯誤的解決(springboot為后臺)
這篇文章主要介紹了vue前臺顯示500和405錯誤的解決(springboot為后臺),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
ElementUI 修改默認樣式的幾種辦法(小結(jié))
這篇文章主要介紹了ElementUI 修改默認樣式的幾種辦法(小結(jié)),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07

