vue2使用vue-pdf实现pdf分页预览及缩放
1. 安装依赖
npm install --save vue-pdf
2. 在需要的页面,引入插件
import pdf from 'vue-pdf'
3. 组件封装完整代码展示
应用:
<template> <pdf-viewer :srcList="Url" style="width: 150px; height: 100px" ></pdf-viewer> </template> <script> import pdfViewer from '@/views/components/pdf-viewer/index' import pdf from 'vue-pdf' export default { components: { pdf, pdfViewer }, data() { return {
url: 'xxxxxx.pdf' } }, methods: { } } </script>
组件:
index.vue
<template> <div> <div v-for="(src, index) in srcList" :key="index" @click="click(src)"> <pdf :src="src" ref="pdf" v-bind="$attrs" class="pdf"></pdf> </div> <el-dialog v-dialogDrag="maxScreen" title="预览" :visible.sync="visible" width="800px;" @closed="close" append-to-body > <pdf-viewer :src="dialogSrc" :startPage="startPage" :style="{ height: height, width: '100%' }" ></pdf-viewer> </el-dialog> </div> </template> <script> import pdf from 'vue-pdf' import pdfViewer from './viewer' export default { components: { pdf, pdfViewer }, props: { srcList: { type: Array, default: () => { return [] } }, startPage: { type: Number, default: 1 } }, data() { return { dialogSrc: '', visible: false, height: '500px' } }, methods: { click(src) { this.dialogSrc = src this.visible = true }, close() { this.dialogSrc = '' }, maxScreen(a) { if (a) { this.height = '500px' } else { this.height = window.innerHeight - 65 + 'px' } } } } </script> <style lang="scss" scoped> .pdf { cursor: pointer; } </style>
viewer.vue
<template> <div class="pdf-viewer" v-if="pdfUrl"> <div class="pdf-bar"> <div class="zoom-minus" @click="zoomMinus"> <i class="el-icon-minus" title="缩小"></i> </div> <div class="scale"> <el-input v-model.number="scale" size="mini" @blur="setScaleValue"> <template slot="append">%</template> </el-input> </div> <div class="zoom-plus" @click="zoomPlus"> <i class="el-icon-plus" title="放大"></i> </div> <div class="prev" @click="prePage"> 上一页 </div> <div class="page"> <el-input-number v-model.number="page" :min="0" :max="pageCount" size="mini" /> </div> <div class="page-count">/ {{ pageCount }}</div> <div class="next" @click="nextPage"> 下一页 </div> </div> <div class="pdf-wrapper"> <pdf :src="pdfUrl" :page="page" @num-pages="pageCount = $event" @page-loaded="currentPage = $event" ref="pdf" ></pdf> </div> </div> </template> <script> import pdf from 'vue-pdf' export default { components: { pdf }, props: { src: String, startPage: { type: Number, default: 1 } }, data() { return { page: 1, currentPage: 0, pageCount: 0, scale: 100, preScale: 100 } }, computed: { pdfUrl() { if (!this.src) return '' const publicPath = process.env.NODE_ENV === 'production' ? process.env.VUE_APP_ROUTER_BASE : '/' return pdf.createLoadingTask({ url: this.src, cMapUrl: `${publicPath}cmaps/`, cMapPacked: true }) } }, watch: { pageCount(value) { if (value) this.page = this.startPage } }, mounted() { }, methods: { setScaleValue(e) { // 输入的不是数字 if (isNaN(e.target.value)) { this.scale = this.preScale return } if (e.target.value < 20) { this.scale = 20 } if (e.target.value > 200) { this.scale = 200 } this.preScale = this.scale this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%' }, zoomMinus() { if (this.scale > 20) { this.scale += -5 this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%' } }, zoomPlus() { if (this.scale < 200) { this.scale += 5 this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%' } }, prePage() { let count = this.currentPage - 1 if (count < 1) return this.page = count }, nextPage() { console.log('this.pageCount', this.currentPage, this.pageCount) let count = this.currentPage + 1 if (count > this.pageCount) return this.page = count } } } </script> <style lang="scss" scoped> .pdf-viewer { position: relative; width: 100%; height: 100%; overflow: hidden; .pdf-bar { position: absolute; top: 0px; left: 0px; z-index: 1; width: 100%; height: 50px; border: 1px solid #ddd; box-sizing: border-box; text-align: center; background: #f8f8f8; display: flex; justify-content: center; align-items: center; & > div { min-width: 36px; height: 36px; line-height: 36px; color: #666; cursor: pointer; i { width: 100%; height: 100%; color: #666; font-weight: bold; } ::v-deep .el-input--mini { input { padding: 0 8px; width: 50px; text-align: center; } .el-input-group__append { padding: 0 6px; color: #666; cursor: auto; } } ::v-deep .el-input-number { margin-left: 10px; width: 40px; .el-input-number__decrease { display: none; } .el-input-number__increase { display: none; } .el-input--mini { input { width: 40px; text-align: center; } } } } .prev { margin-left: 16px; } .scale, .page { display: flex; align-items: center; } .page-count { margin-right: 10px; } } .pdf-wrapper { position: absolute; margin-top: 50px; width: 100%; height: calc(100% - 50px); overflow: auto; } } </style>
效果图: