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>

效果图:

 

posted @ 2024-04-19 15:43  QianTM  阅读(160)  评论(0编辑  收藏  举报