效果预览
- 下载插件
npm install pdfjs-dist@2.15.349
- 封装组件
2.1 找到node-modules>pdfjs-dist文件夹, 把build、cmaps、web文件夹整个复制到
static>pdf(新建pdf文件夹,把那三个小文件夹复制到这里,一个都不能少!!!!!!)
2.2 新建第三方封装getPdfjsDist.js 获取文件方法
const getJavsScript = (src) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.onload = resolve
script.onerror = reject
script.src = src
document.body.append(script)
})
}
const getCss = (href) => {
return new Promise((resolve, reject) => {
const link = document.createElement('link')
link.onload = resolve
link.onerror = reject
link.setAttribute('rel', 'stylesheet')
link.setAttribute('type', 'text/css')
link.href = href
document.body.append(link)
})
}
const getPdfjsDist = (pdfjsDistPath) => {
return getJavsScript(`${pdfjsDistPath}/pdf/build/pdf.js`)
.then(() => {
return Promise.all([
getJavsScript(`${pdfjsDistPath}/pdf/web/pdf_viewer.js`),
getCss(`${pdfjsDistPath}/pdf/web/pdf_viewer.css`)
])
})
}
export default getPdfjsDist
2.3 预览pdf文件
<template>
<div>
<div class="div" v-show="show">
<div class="tools-bar"><a class="close" @click="close"><van-icon name="cross"></van-icon></a></div>
<div class="pdf-view">
<div id="viewerContainer" ref="container">
<div id="viewer" class="pdfViewer"></div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { onMounted, ref, unref, watch } from 'vue'
import getPdfjsDist from './getPdfjsDist'
export default {
name: 'PdfViewer',
components: {
// VuePdfEmbed
},
props: {
show: { type: Boolean, default: false, },
url: { type: String, default: '' } // pdf文件路径
},
setup(props, ctx) {
let pdfjsDistPath: string = "./static";
// if (window.location.pathname.endsWith("index.html")) {
// pdfjsDistPath = window.location.origin + window.location.pathname.replace("index.html", "") + "static";
// } else {
// pdfjsDistPath = window.location.origin + window.location.pathname + "static";
// }
const type = "canvas";
let pdfViewer: any = null;
let pdfLinkService: any = null;
let currentScale = "page-width";
let loadingTask: any = null;
let CMAP_URL = "";
const container = ref();
async function pdfLibInit() {
let pdfjsLib = (window as any).pdfjsLib;
let pdfjsViewer = (window as any).pdfjsViewer;
if (!pdfjsLib || !pdfjsViewer) {
try {
await getPdfjsDist(pdfjsDistPath)
CMAP_URL = `${pdfjsDistPath}/pdf/cmaps/`;
pdfjsLib = (window as any).pdfjsLib;
pdfjsLib.GlobalWorkerOptions.workerSrc = `${pdfjsDistPath}/pdf/build/pdf.worker.js`
pdfjsViewer = (window as any).pdfjsViewer;
} catch (error) {
// console.log(error)
// pdfjs文件获取失败
return
}
}
const containerRef = container.value
const eventBus = new pdfjsViewer.EventBus();
// (Optionally) enable hyperlinks within PDF files.
const pdfLinkServiceTmp = new pdfjsViewer.PDFLinkService({
eventBus: eventBus,
});
pdfLinkService = pdfLinkServiceTmp
const pdfViewerTmp = new pdfjsViewer.PDFViewer({
container: containerRef,
eventBus: eventBus,
linkService: pdfLinkService,
renderer: type,
textLayerMode: 0,
downloadManager: new pdfjsViewer.DownloadManager({}),
enableWebGL: true
});
pdfViewer = pdfViewerTmp
pdfLinkService.setViewer(pdfViewer);
eventBus.on("pagesinit", function ({ source }) {
source.currentScaleValue = currentScale;
});
}
function renderPdf() {
if (!props.url) {
return
}
// Loading document.
if (pdfViewer === null || pdfLinkService === null) {
return
}
if (loadingTask !== null) {
loadingTask.destroy()
loadingTask = null
}
loadingTask = (window as any).pdfjsLib.getDocument({
// cMapUrl: CMAP_URL, // 原来是相对路径 但是会报错提示字体找不到 后来换了绝对路径 或 线上字体地址 都可以正常使用
cMapUrl: window.location.origin+ '/static/pdf/cmaps/', // 绝对路径
// cMapUrl: 'https://unpkg.com/pdfjs-dist@2.15.349/cmaps/', // 线上字体地址
cMapPacked: true,
url: props.url,
});
return loadingTask.promise.then((pdfDocument) => {
if (pdfDocument.loadingTask.destroyed || !props.url) {
return
}
pdfViewer.setDocument(pdfDocument)
pdfLinkService.setDocument(pdfDocument, null);
loadingTask = null
ctx.emit('load-ok')
}).catch(error => {
console.log(error)
});
}
const close = function () {
ctx.emit('on-ok', false)
}
onMounted(() => {
pdfLibInit().then(() => {
renderPdf()
})
})
watch(() => props.url, (newVal, oldVal) => {
console.log(props.url)
if (pdfViewer) {
pdfViewer._cancelRendering()
}
renderPdf();
}, { deep: true })
return {
container,
close,
}
}
}
</script>
<style scoped lang="less">
.div {
top: 50px;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
z-index: 999;
overflow: auto;
}
.tools-bar {
position: fixed;
top: 50px;
right: 0;
left: 0;
z-index: 9;
display: flex;
justify-content: flex-end;
.close {
padding: 15px;
display: flex;
justify-content: center;
align-items: center;
&:before {
content: "";
width: 30px;
height: 30px;
background-color: rgba(0, 0, 0, .3);
border-radius: 50%;
}
i {
position: absolute;
font-size: 1.8rem;
color: #fff;
}
}
}</style>
- 使用
<template>
<div>
<pdfViewer :show="pdfViewSource.show" :url="pdfViewSource.url" @on-ok="pdfViewSource.show = false"></pdfViewer>
</div>
</template>
<script type="module" lang="ts">
import pdfViewer from './pdfView/index.vue'
export default defineComponent({
components: {pdfViewer},
setup () {
const filePreviewClick = (source:any)=>{
let url:any = source.url
pdfViewSource.url = url
pdfViewSource.show = true
}
}
})
</script>