vue中运用vue-pdf实现pdf分页预览及缩放(可解决pdf预览不清晰问题)

场景:前端在实现pdf预览时,需要实现分页预览和缩放功能,同时需要保证pdf的清晰度。

但因为种种原因,不可以接通过iframe标签将pdf文件引入,让用户直接使用浏览器自带的pdf预览的相关工具。而是需要自己通过代码实现上述两个功能。

注:若可以直接使用iframe引入 是比较简单的 关于iframe直接引入的方式可见这里

vue中前端实现pdf预览(含vue-pdf插件用法)https://blog.csdn.net/m0_71537867/article/details/129918181

实现效果:

本次封装的组件的实现效果展示如下

实现思路:

1. 使用vue-pdf插件来实现预览功能。

2. 上一页/下一页按钮的点击事件中,改变当前当页码,实现翻页功能。

扫描二维码关注公众号,回复: 16001533 查看本文章

3. 缩放按钮的点击事件中,改变pdf预览插件所在容器的css样式-----transform:scale(),实现缩放功能。

注: 也曾试过直接去改变pdf预览插件所在容器的宽度来实现缩放效果,这种实现方案较为简单,动态改变容器的width就可以。但是若pdf的内容中主要是文字,就会出现文字清晰度不够的问题。哈哈哈 残酷!

实现步骤:

1.  安装依赖

npm install --save vue-pdf

2. 在需要的页面,引入插件

import pdf from 'vue-pdf'

3. 组件封装完整代码展示

html部分

<template>
  <div 
    class="pdf-preview-out"
    v-loading="boxLoading"
  >
    <!-- 上部 外层容器 用于滚动-->
    <div class="scroll-box">
      <!-- 用于截取调缩放后的空白区域 -->
      <div class="pdf-box">
        <!-- pdf预览区域(会被缩放) -->
        <div
          :style="getPdfSize()" 
          class="pdf-scale-box"
        >
          <!-- 预览组件 -->
          <pdf
            :src="url"
            :page="currentPage"
            @num-pages="getTotalPage"
            @page-loaded="pageLoaded"
            @loaded="mountedLoaded"
          >
          </pdf>
        </div>
      </div>
    </div>

    <!-- 底部操作栏 -->
    <div class="bottom-tools">
      <div>
        共 {
   
   { pageTotal }} 页
      </div>
      <div class="page">
        <el-button
          round
          type="primary"
          :disabled="currentPage === 1"
          @click="chengPage"
        >
          上一页
        </el-button>
        <!-- 页码展示及跳转 -->
        <el-button
          round
          type="primary"
          :disabled="currentPage === pageTotal"
          @click="chengPage('+')"
        >
          下一页
        </el-button>
      </div>

      <div class="scale">
        <el-button 
          type="primary"
          icon="el-icon-minus" 
          circle
          :disabled="(pageScale - 0.1) < 0.3"
          @click="scalePage"
        >
        </el-button>
        <el-button 
          type="primary"
          icon="el-icon-plus" 
          circle
          :disabled="(pageScale + 0.1) > 1"
          @click="scalePage('+')"
        >
        </el-button>
      </div>
    </div>
  </div>
</template>

JS部分

<script>
// 插件引入
import pdf from 'vue-pdf'
export default {
  components: {
    pdf
  },
  props: {
    // pdf预览的地址 由父组件中传入 也可在本组件中直接赋值
    url: {
      type: String,
      default: ''
    },
  },
  data() {
    return {
      // 总页数
      pageTotal: 0,
      // 当前页
      currentPage: 1,
      // 缩放比例
      pageScale: 0.8,
      // 遮罩
      boxLoading: true,
      pageChangeTimer: null,
    }
  },
  methods: {
    // 获取到pdf总页数时触发 会传入总页数
    getTotalPage(page) {
      this.pageTotal = page
    },
    // 初始化加载完毕触发
    mountedLoaded() {
      // 去除遮罩
      this.boxLoading = false
    },
    // 每加载完成一页时触发(初始化/翻页时均会触发)
    pageLoaded() {
      // 重新设置pdf预览区域容器外容器的尺寸
      this.setPdfBoxSize()
    },
    // 设置pdf预览区域容器的缩放尺寸
    getPdfSize() {
      return {
        transform: `scale(${this.pageScale})`
      }
    },
    // 点击缩放时触发
    scalePage(type) {
      // 改变缩放比例
      let sacle = 0
      if (type === '+') {
        sacle = this.pageScale + 0.1
      } else {
        sacle = this.pageScale - 0.1
      }
      // 可能会涉及js的精度损失 保留一位小数即可
      this.pageScale = Number(sacle.toFixed(1))
      // 缩放后pdf预览区域容器中会有留白 重新设置pdf预览区域容器外容器的尺寸
      this.setPdfBoxSize()
    },
    // 方法 翻页
    chengPage(type) {
      // 防抖 0.5秒内不再次触发时执行
      if (this.pageChangeTimer) {
        clearTimeout(this.pageChangeTimer)
      }
      // 执行翻页
      this.pageChangeTimer = setTimeout(() => {
        if (type === '+') {
          this.currentPage+=1
        } else {
          this.currentPage-=1
        }
        // 翻页后将滚动条归位到顶部
        this.scrollbarReset()
        this.pageChangeTimer = null
      }, 500)
    },
    // 方法 滚动条归位到顶部
    scrollbarReset() {
      let boxDom = document.querySelector('.scroll-box')
      boxDom.scrollTop = 0
    },
    // 方法 设置pdf预览区域容器外容器的尺寸
    setPdfBoxSize() {
      // 缩放后 pdf的显示上会缩小 但元素的实际占地尺寸不会变化(仍是原尺寸) 导致可能会出现部分区域留白 通过改变pdf预览区域容器外容器的尺寸 来将留白区域hidden
      // 获取pdf的原尺寸
      let boxDom = document.querySelector('.pdf-scale-box')
      // 获取要设置尺寸的元素dom
      let setDom = document.querySelector('.pdf-box')
      // 如有缩放 高度根据缩放比例变化(48px是预留的上下外边距)
      if (this.pageScale !== 1 && boxDom && setDom) {
        setDom.style.height = `${boxDom.clientHeight *  this.pageScale + 48}px`
      } else {
        setDom.style.height = ''
      }
      // console.log(this.pageScale)
      // console.log(boxDom.clientWidth *  this.pageScale)
    }
  }
}
</script>

css部分

<style lang="scss" scoped>
.pdf-preview-out {
  // 高度为占满父组件中的外层容器(若不需要在父组件中设置高度 也可以在本组件中直接设置为所需值)
  height: 100%;
  // border: 1px solid #909;
  &, div {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
  }
  // 滚动容器
  .scroll-box {
    // 高度按比例 溢出滚动
    height: calc(100% - 50px);
    overflow: auto;
    border: 2px solid #c0d8f3;
    border-bottom: none;
    border-radius: 6px;
    background-color: #eeeeee;
    // 滚动条样式
    &::-webkit-scrollbar {
      width: 10px;
    }
    &::-webkit-scrollbar-thumb {
      background-color: #c0d8f3;
      border-radius: 6px;
    }
    &::-webkit-scrollbar-track {
      background-color: transparent;
      border-radius: 6px;
    }
    // 用于缩放后截取掉不需要的空白的容器
    .pdf-box {
      overflow: hidden;
      padding: 24px;
      // border: 1px solid rgb(165, 11, 236);
    }
    // pdf预览区容器
    .pdf-scale-box {
      box-shadow: 0px 0px 20px 5px #666565;
      // border: 2px solid #090;
      // 设置缩放的中心点
      transform-origin: center top;
      transition: .2s;
    }
  }
  .bottom-tools {
    height: 50px;
    line-height: 50px;
    background-color: #c0d8f3;
    border: 1px solid #5caaf8;
    border-radius: 6px;
    display: flex;
    padding: 0px 24px;
    .page {
      color: #636a70;
      flex-grow: 1;
      // border: 1px solid #909;
      span {
        margin-right: 20px; 
      }
    }
    .scale {
      // border: 1px solid #909;
      text-align: right;
    }
  }
}
</style>

至此,pdf预览组件就已经愉快的封装完毕。在需要的地方将本组件引入并传入获取到的pdf预览地址,同时按需给本组件引入到的外层容器设置高度,即可实现pdf的翻页预览、缩放效果。

猜你喜欢

转载自blog.csdn.net/m0_71537867/article/details/131614868