vue-pdf 展示出现字体丢失问题
解决办法:重写两个js CMapReaderFactory buffer-loader
// CMapReaderFactory.js
import { CMapCompressionType } from 'pdfjs-dist/es5/build/pdf.js'
// see https://github.com/mozilla/pdf.js/blob/628e70fbb5dea3b9066aa5c34cca70aaafef8db2/src/display/dom_utils.js#L64
export default function() {
this.fetch = function(query) {
return import('./buffer-loader!pdfjs-dist/cmaps/' + query.name + '.bcmap' /* webpackChunkName: "noprefetch-[request]" */)
.then(function(bcmap) {
delete require.cache[require.resolve('./buffer-loader!pdfjs-dist/cmaps/' + query.name + '.bcmap')]
return {
cMapData: bcmap.default,
compressionType: CMapCompressionType.BINARY
}
})
}
}
// buffer-loader
module.exports = function(content) {
var data;
if ( content instanceof Buffer )
data = content;
else
data = Buffer.from(content);
return 'export default Buffer.from("'+data.toString('base64')+'", "base64")';
}
module.exports.raw = true;
pdf vue组件
<template>
<!-- 弹窗组件 -->
<!-- top="20vh" 距离浏览器上面距离 -->
<elian-dialog
ref="ElianPdf"
:visible.sync="visible"
top="1vh"
:width="widths"
:title="pageNum + '/' + pageTotalNum"
destroy-on-close
@close="beforeClosed"
>
<div class="pdf" :style="{ height: heights + 'px' }">
<div class="main">
<pdf
ref="pdf"
:src="pdfUrl"
:page="pageNum"
:rotate="pageRotate"
@password="password"
@progress="loadedRatio = $event"
@page-loaded="pageLoaded($event)"
@num-pages="pageTotalNum = $event"
@error="pdfError($event)"
@link-clicked="page = $event"
>
</pdf>
</div>
<div class="flexbox">
<div class="btn-def btn-pre" @click.stop="prePage">
<img src="@/assets/images/syy.png" width="26px" alt="" />
</div>
<div class="btn-def btn-next" @click.stop="nextPage">
<img src="@/assets/images/xyy.png" width="26px" alt="" />
</div>
<div
:class="{ select: idx == 0 }"
@touchstart="idx = 0"
@touchend="idx = -1"
@click="scaleD"
>
<img src="@/assets/images/fd.png" width="26px" alt="" />
</div>
<div
:class="{ select: idx == 1 }"
@touchstart="idx = 1"
@touchend="idx = -1"
@click="scaleX"
>
<img src="@/assets/images/sx.png" width="26px" alt="" />
</div>
<div @click="fileDownload(pdfUrl)">
<img src="@/assets/images/xz.png" width="22px" alt="" />
</div>
</div>
</div>
</elian-dialog>
</template>
<script>
import download from 'downloadjs'
import pdf from 'vue-pdf'
import CMapReaderFactory from './CMapReaderFactory.js'
export default {
name: 'ElianPdf',
components: {
pdf
},
data() {
return {
pdfUrl: '',
pageNum: 1,
pageTotalNum: 1,
loadedRatio: 0, // 加载进度
curPageNum: 0,
pageRotate: 0,
scale: 70, //放大系数
idx: -1,
visible: false,
heights: '',
widths: '',
fileList: []
}
},
computed: {},
created() {
this.heights = window.innerHeight - 90
},
methods: {
pdfTask(pdfUrl){
var self = this
// 传参 CMapReaderFactory
this.pdfUrl = pdf.createLoadingTask({url: pdfUrl, CMapReaderFactory})
this.pdfUrl.promise.then(pdf => {
self.numPages = pdf.numPages
}).catch((err) => {
console.error('pdf加载失败')
})
},
open(fileurl) {
//this.pdfUrl = fileurl
this.pdfTask(fileurl)
this.visible = true
},
/**
* 确定 - 调用父页面新增操作
*/
handleSubmit() {
this.visible = false
},
/**
* 关闭 - 当前弹窗,并刷新父页面
*/
beforeClosed() {
this.visible = false
},
fileDownload(item) {
// console.log(item)
// let fileurls
// fileurls = window.location.origin + item
download(item)
},
//放大
scaleD() {
if (this.scale == 100) {
return
}
this.scale += 5
// this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%'
this.widths = parseInt(this.scale) + '%'
},
//缩小
scaleX() {
if (this.scale == 40) {
return
}
this.scale += -5
// this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%'
this.widths = parseInt(this.scale) + '%'
},
prePage() {
var p = this.pageNum
p = p > 1 ? p - 1 : this.pageTotalNum
this.pageNum = p
},
nextPage() {
var p = this.pageNum
p = p < this.pageTotalNum ? p + 1 : 1
this.pageNum = p
},
password(updatePassword, reason) {
updatePassword(prompt('password is "123456"'))
console.log('...reason...')
console.log(reason)
console.log('...reason...')
},
pageLoaded(e) {
this.curPageNum = e
},
pdfError(error) {
console.error(error)
},
pdfPrintAll() {
this.$refs.pdf.print()
},
pdfPrint() {
this.$refs.pdf.print(100, [1, 2])
}
}
}
</script>
<style lang="scss" scoped>
.pdf {
overflow: auto;
width: 100%;
& .flexbox {
display: flex;
position: fixed;
width: 260px;
height: 36px;
padding: 10px 16px;
left: -webkit-calc(50% - 130px);
left: -moz-calc(50% - 130px);
left: calc(50% - 130px);
bottom: 20px;
background: rgba(170, 170, 170, 0.6);
border-radius: 20px;
& div {
width: 25%;
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>