vue-pdf出现打印乱码、方块字、无法打印
项目中需要用到vue-pdf组件来进行pdf的预览和打印,但使用vue-pdf打印图片没有问题,打印字体转码的PDF文件流会出现方块字。
各大社区找解决办法,有修改pdfjsWrapper.js源码的报错(loadingTask.then is not a function)、有使用 vue-print-nb组件的等等,各大坑都踩遍了,查百度把手都查出血了,没找到解决问题的办法。
最终解决问题的办法是使用iframe.conentwindow.print()。
以下是关键部分的代码标注:
选中当前iframe打印:
onPrint() {
document.getElementById('printIframe').contentWindow.print();
},
问题完美解决。
附上完整代码,供copy,包含pdf打印、分页、滚动页面pdf页码更新。
<template>
<div class="contain">
<div class="module">
<div class="icon">
<span></span>
</div>
<div class="detail">
<div class="detail-left">
<div class="title">
<div class="titleIcon"></div>
<p>{{ pdfTitle }}</p>
</div>
<div class="time">发布时间 {{ pdfTime | datetimeFormat }}</div>
<div class="module-button">
<el-button class="download" type="primary" @click="onDownload">
下载
<div class="titleIcon"></div>
</el-button>
<el-button class="download" type="primary" @click="onPrint">
打印
<div class="secondBtn"></div>
</el-button>
</div>
</div>
<div class="detail-right">
<img :src="smallJpg" alt="" />
</div>
</div>
</div>
<div class="pdfBody">
<div class="pdfHeader">
<div class="pagination">
<el-input v-model="input" placeholder="" size="mini " style="margin: 10px" @change="pageHander"></el-input>
<div>/</div>
<span>{{ numPages }}</span>
</div>
</div>
<!-- 吸顶标题 -->
<div v-show="isShow" class="scrollBox">
<div class="scrollBox-left">
<div class="titleIcon"></div>
<p>{{ pdfTitle }}</p>
</div>
<div class="pagination">
<el-input v-model="input" placeholder="" size="mini " style="margin: 10px" @change="pageHander"></el-input>
<div>/</div>
<span>{{ numPages }}</span>
</div>
<div class="scrollBox-right">
<div class="downLoad" @click="onDownload"></div>
<div class="print" @click="onPrint"></div>
</div>
</div>
<div ref="printContent">
<pdf v-for="i in numPages" :key="i" ref="pdfContent" :src="src" :page="i" style="display: inline-block; width: 100%"></pdf>
</div>
<iframe id="printIframe" :src="iframesrc" frameborder="0" style="display:none"></iframe>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf';
export default {
name: 'PdfViewer',
components: { pdf },
data() {
return {
input: 1,
isShow: false,
pageCount: 0,
scrollDistance: 0,
pdfTitle: this.$route.query.name,
pdfTime: this.$route.query.time,
smallJpg: this.$route.query.smallJpg,
iframesrc: this.$route.query.src,
src: pdf.createLoadingTask(this.$route.query.src),
numPages: 0,
};
},
created() {},
mounted() {
this.src.promise.then((pdf) => {
this.numPages = pdf.numPages;
});
window.addEventListener('scroll', this.scrollHandler);
},
unmounted() {
window.addEventListener('scroll', this.scrollHandler);
},
methods: {
initData() {
this.pdfTitle = this.$route.query.name;
this.pdfTime = this.$route.query.time;
this.smallJpg = this.$route.query.smallJpg;
},
pageHander() {
if (this.input > this.numPages || this.input === Number(0)) {
this.$message({
showClose: true,
message: '已超过文件页数!',
});
}
const soloPdfHeight = this.$refs.printContent.offsetHeight / this.numPages;
document.documentElement.scrollTop = this.input == 1 ? 0 : this.input * soloPdfHeight + 400;
},
scrollHandler() {
this.scrollDistance = document.documentElement.scrollTop;
const soloPdfHeight = this.$refs.printContent.offsetHeight / this.numPages;
this.input = this.scrollDistance > 400 ? Math.ceil((this.scrollDistance - 400) / soloPdfHeight) : 1;
console.log(this.input);
if (this.scrollDistance > 335) {
// 滚动条滚动距离超过100时
this.isShow = true;
} else {
this.isShow = false;
}
},
onDownload() {
this.$api.download(`file/downloadFile?fileId=${this.$route.query.id}`).then((res) => {});
},
onPrint() {
document.getElementById('printIframe').contentWindow.print();
},
},
};
</script>
<style lang="scss" scoped>
// 吸顶
::v-deep.el-dialog__headerbtn {
font-size: 12px;
}
::v-deep .el-input--mini .el-input__inner {
color: #adb1b8;
width: 28px;
height: 28px;
text-align: center;
padding: 0px;
background: #525a66;
font-size: 14px;
}
.scrollBox {
background: #363e47;
border: 1px solid #313d4f;
border-radius: 4px 4px 0 0;
position: fixed;
height: 40px;
top: 70px;
margin-right: 30px;
z-index: 1000000000;
display: flex;
align-items: center;
width: 84.8%;
.pagination {
display: flex;
position: absolute;
left: 50%;
color: #adb1b8;
align-items: center;
justify-content: space-around;
width: 70px;
div {
text-align: center;
margin-right: 6px;
}
span {
}
}
.scrollBox-right {
position: absolute;
right: 60px;
display: flex;
width: 60px;
justify-content: space-between;
.print {
width: 18px;
height: 22px;
cursor: pointer;
background: url('~@/assets/icons/dayin.svg') no-repeat;
background-size: 100%;
}
.downLoad {
width: 18px;
height: 22px;
line-height: 22px;
cursor: pointer;
background: url('~@/assets/icons/xiazai2.svg') no-repeat;
background-size: 100%;
}
}
.scrollBox-left {
display: flex;
align-items: center;
justify-content: center;
p {
width: 400px;
margin: 30px;
font-family: PingFangSC-Semibold;
font-size: 14px;
color: #ffffff;
letter-spacing: 0.39px;
line-height: 18px;
}
.titleIcon {
margin-left: 32px;
width: 18px;
height: 22px;
cursor: pointer;
background: url('~@/assets/icons/wendang1.svg') no-repeat;
background-size: 100%;
}
}
}
.contain {
width: 100%;
height: 100%;
.module {
padding: 25px 0px;
margin-bottom: 37px;
.detail {
padding: 22px;
display: flex;
justify-content: space-between;
align-items: center;
height: 120px;
width: 100%;
.detail-right {
width: 100px;
height: 140px;
margin-right: 20px;
img {
width: 100%;
height: 100%;
}
}
.detail-left {
//font-family: PingFangSC-Semibold;
font-weight: bold;
font-size: 20px;
color: #ffffff;
.module-button {
margin-top: 20px;
display: flex;
.download {
height: 28px;
width: 80px;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.titleIcon {
width: 16px;
height: 14px;
position: absolute;
right: 8px;
top: 6px;
cursor: pointer;
background: url('~@/assets/icons/xiazai2.svg') no-repeat;
background-size: 100%;
}
.secondBtn {
width: 16px;
height: 14px;
position: absolute;
right: 8px;
top: 6px;
cursor: pointer;
background: url('~@/assets/icons/dayin.svg') no-repeat;
background-size: 100%;
}
}
}
.time {
opacity: 0.7;
font-family: PingFangSC-Semibold;
font-size: 14px;
color: #ffffff;
height: 18px;
letter-spacing: 0.39px;
line-height: 18px;
}
.title {
display: flex;
justify-content: space-between;
.titleIcon {
width: 32px;
height: 38px;
margin-right: 10px;
cursor: pointer;
background: url('~@/assets/icons/wendang1.svg') no-repeat;
background-size: 100%;
}
}
}
}
.icon {
border-bottom: 1px solid rgba(61, 61, 61, 0.4);
height: 28px;
margin-bottom: 10px;
position: relative;
top: -12px;
span {
opacity: 0.7;
font-family: PingFangSC-Semibold;
font-size: 14px;
padding: 0px 10px 12px 30px;
color: #ffffff;
letter-spacing: 2px;
line-height: 18px;
}
}
}
.pdfBody {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
border-radius: 8px 8px 0 0;
.pdfHeader {
background: #363e47;
border: 1px solid #313d4f;
border-radius: 8px 8px 0 0;
position: relative;
height: 40px;
top: 0px;
z-index: 10;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
.pagination {
display: flex;
color: #adb1b8;
align-items: center;
justify-content: space-around;
width: 70px;
div {
text-align: center;
margin-right: 6px;
}
span {
}
}
}
}
}
</style>