当前位置: 首页 > article >正文

vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题

vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题

插件介绍

pdfdist-mergeofd插件的作用可查看这篇文章,同时使用ofdjs和pdfjs遇到的问题,和解决方法——懒加载

该插件主要是为了解决pdfjs和ofdjs同时使用时产生的兼容性问题,用法与pdfjs一致

实现预览pdf

<!-- 使用el-upload获取上传的文件 -->
 <el-upload
   ref="upload"
   action
   :accept="fileType"
   :on-change="onChangeFile"
   :before-upload="beforeFileUpload"
   :show-file-list="false"
   :auto-upload="false"
 >
   <el-button slot="trigger" type="primary">选择文件</el-button>
 </el-upload>
 <!-- 控制翻页 -->
 <div v-if="pageCount" style="text-align: center">
   <el-button :disabled="currentPage == 1" @click="clickPre">
     上一页
   </el-button>
   <span>第{{ currentPage }} / {{ pageCount }}页</span>
   <el-button :disabled="currentPage == pageCount" @click="clickNext">
     下一页
   </el-button>
 </div>
<!-- html部分非常简单,创建一个canvas用于后续渲染即可 -->
<div
     ref="canvasCont"
     class="canvas-container"
   >
     <canvas ref="myCanvas" class="pdf-container"></canvas>
</div>
//这里是用的pdfdist-mergeofd,如果使用pdfjs,用法一致
import * as pdfJS from 'pdfdist-mergeofd'

pdfJS.GlobalWorkerOptions.workerSrc = require('pdfdist-mergeofd/build/pdf.worker.entry')

export default {
  name: 'xxx',
  data() {
    return {
      file: null,
      //页面宽度,根据实际调整
      pageWidth: 800,
      //页面高度,根据实际调整
      pageHeight: 1131,
      //当前页数
      currentPage: 0,
      //总页数
      pageCount: 0,
      pdfSrc: null,
      //尺寸限制
      sizeLimit: 1 * 1024 * 1024,
      //是否正在渲染页面,防止过快翻页
      renderingPage: false,
    }
  },
  methods: {
    // 上传文件
    async onChangeFile({ raw }) {
      if (!this.beforeFileUpload(raw)) {
        return
      }
      if (!raw) {
        return
      }
      this.file = raw
      if (raw.type === 'application/pdf') {
        const reader = new FileReader()
        this.currentType = 'pdf'
        reader.onload = async e => {
          this.pdfSrc = e.target.result
          let data = atob(
            reader.result.substring(reader.result.indexOf(',') + 1)
          )
          this.loadPdfData(data)
        }
        reader.readAsDataURL(raw)
      }
    },
    loadPdfData(data) {
      // 引入pdf.js的字体
      let CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.943/cmaps/'
      //读取base64的pdf流文件
      this.pdfData = pdfJS.getDocument({
        data: data,
        cMapUrl: CMAP_URL,
        cMapPacked: true
      })
      this.renderPage(1)
    },
    // 上一页
    clickPre() {
        if (!this.renderingPage && this.currentPage && this.currentPage > 1) {
          this.renderPage(this.currentPage - 1)
        }
      }
    },
    //下一页
    clickNext() {
        if (
          !this.renderingPage &&
          this.currentPage &&
          this.currentPage < this.pageCount
        ) {
          this.renderPage(this.currentPage + 1)
        }
      }
    },
    // 根据页码渲染相应的PDF
    renderPage(num) {
      this.renderingPage = true
      this.pdfData.promise.then(pdf => {
        this.pageCount = pdf.numPages

        pdf.getPage(num).then(page => {
          // 获取DOM中为预览PDF准备好的canvasDOM对象
          let canvas = this.$refs.myCanvas
          let ctx = canvas.getContext('2d')

          // 获取页面比率
          let ratio = window.devicePixelRatio || 1
          console.log(ratio)

          // 根据页面宽度和视口宽度的比率就是内容区的放大比率
          let dialogWidth = this.$refs['canvasCont'].offsetWidth
          let pageWidth = page.view[2] * ratio
          let scale = dialogWidth / pageWidth
          let viewport = page.getViewport({ scale: scale * 2 })

          canvas.width = viewport.width * ratio
          canvas.height = viewport.height * ratio

          // 缩放比率
          ctx.setTransform(ratio, 0, 0, ratio, 0, 0)

          let renderContext = {
            transform: [1, 0, 0, 1, 0, 0],
            canvasContext: ctx,
            viewport: viewport
          }
          page.render(renderContext).promise.then(() => {
            this.renderingPage = false
            this.currentPage = num
          })
        })
      })
    },
    // 计算角度
    _getRatio(ctx) {
      let dpr = window.devicePixelRatio || 1
      let bsr =
        ctx.webkitBackingStorePixelRatio ||
        ctx.mozBackingStorePixelRatio ||
        ctx.msBackingStorePixelRatio ||
        ctx.oBackingStorePixelRatio ||
        ctx.backingStorePixelRatio ||
        1
      return dpr / bsr
    },
    beforeFileUpload(file) {
      const fileName = file.name
      const fileType = this.fileType.split(',')
      if (fileType.every(item => !fileName.endsWith(item))) {
        this.$tip.warning(`请选择格式为${fileType.join('或')}类型的文件`)
        return false
      }
      const { sizeLimit, sizeLimitWithUnit } = this
      if (file.size > sizeLimit) {
        this.$tip.warning(`文件大小不能超过${sizeLimitWithUnit},请重新选择`)
        return false
      }
      return true
    },
  }
}

解决pdf显示模糊

很多文章介绍说调整显示区域大小,这样确实可以提高清晰度,当时当显示区域有限时就无法解决,因此解决方案采用将渲染canvas区域的scale翻倍,同时通过css的transform属性将区域大小设置成原来的一半。
这种方法的原理是增加渲染区域的物理像素数,从而提高图像的分辨率。
参考文章提高PDF预览的清晰度

.pdf-container {
  transform: scale(0.5);
  transform-origin: top left;
}

效果展示

这是修改之前显示pdf的质量
在这里插入图片描述
这是修改之后的质量,变清晰了许多
在这里插入图片描述


http://www.kler.cn/a/373260.html

相关文章:

  • 基于SSM学生竞赛模拟系统的设计
  • 【综合算法学习】(第十篇)
  • Unreal Engine 5 C++(C#)开发:使用蓝图库实现插件(一)认识和了解Build.cs
  • 排序算法汇总
  • 2020年下半年网络规划设计师上午真题及答案解析
  • 代码随想录day15 二叉树(3)
  • 【算法与数据结构】二分查找思想
  • 海外媒体发稿:如何打造媒体发稿策略
  • 【SSM详细教程】-13-SpringMVC详解
  • Convolution 卷积
  • QT 实现自定义动态选择指示器
  • git的学习之远程进行操作
  • AIGC与教育行业的邂逅--其在数学领域的应用与实现
  • 【代码随想录Day55】图论Part07
  • 后台管理系统的通用权限解决方案(二)SpringBoot整合Swagger Springfox实现接口日志文档
  • Android系统架构
  • 新品上市|RNA提取系列上市了!
  • 和鲸科技 CEO 范向伟受邀揭牌启动南京大学 2024 级大学生人工智能素养大赛
  • 数据库真的是能够决定架构的
  • 论文提交步骤 | 2024年第五届MathorCup大数据竞赛
  • 阿里云物联网的通信方式
  • C++第九讲:模板进阶
  • 第三方软件检测公司分享:软件性能测试有哪些好用的测试工具?
  • 机器人技术基础(4章逆运动解算和雅克比矩阵)
  • wsl 使用docker 部署oracle11g数据库
  • IDEA集成JProfiler