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的质量
在这里插入图片描述
这是修改之后的质量,变清晰了许多
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习:yolov3的使用--建立模型

使用argparse模块来定义和解析命令行参数 创建一个ArgumentParser对象 parser argparse.ArgumentParser() 训练的轮数&#xff0c;每批图像的大小&#xff0c;更新模型参数之前累积梯度的次数,模型定义文件的路径。 parser.add_argument("--epochs", typeint, d…

38.第二阶段x86游戏实战2-HOOK窗口消息机制(解决多开窗口句柄问题)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

详解汉明纠错码原理以及FPGA实现

文章目录 一、汉明纠错码简介二、汉明码编码原理以及步骤三、汉明码纠错原理以及步骤四、FPGA实现74汉明编码器五、FPGA实现74汉明解码器 一、汉明纠错码简介 汉明纠错码&#xff08;Hamming Code&#xff09;是一种用于检测和纠正数据传输中错误的编码方法。它由理查德汉明&am…

无人机光电识别跟踪算法!

一、算法概述 无人机光电识别跟踪算法结合了可见光和红外成像技术&#xff0c;通过光学系统收集目标的光学信息&#xff0c;并将其转换为电信号进行处理和分析。该算法能够实现对目标的快速、准确识别与追踪&#xff0c;极大提升了无人机在复杂环境下的作业能力和效率。 二、…

Ethernet 系列(6)-- 基础学习::OSI Model

&#xff08;写在前面&#xff1a;最近在学习车载以太网的知识&#xff0c;顺便记录一下知识点。&#xff09; OSI&#xff08;Open System Interconnect &#xff09;模型是一种网络通信框架&#xff0c;由国际标准化组织&#xff08;‌ISO&#xff09;在1985年提出&#xff0…

day15:shell基础

一&#xff0c;编程语法分类&#xff08;了解&#xff09; 编程范式&#xff1a; 面向过程&#xff1a;程序通过按步骤执行函数或过程完成任务&#xff0c;强调流程控制和函数调用&#xff0c;适合流程明确的任务&#xff0c;如 C。面向对象&#xff1a;通过“类”和“对象”封…

无人机测绘遥感技术算法概述!

一、数据采集算法 航线规划算法 根据测绘任务需求&#xff0c;利用地理信息系统&#xff08;GIS&#xff09;和遥感技术&#xff0c;对无人机进行航线规划。 考虑地形、气候、障碍物等因素&#xff0c;优化飞行路径&#xff0c;确保数据采集的完整性和准确性。 传感器控制算…

Pytest-Bdd-Playwright 系列教程(6):在测试步骤函数中设置别名数据共享

Pytest-Bdd-Playwright 系列教程&#xff08;6&#xff09;&#xff1a;在测试步骤函数中设置别名&数据共享 前言一、步骤别名二、特性文件三、测试脚本四、运行测试五、小测验总结 前言 有的时候&#xff0c;为了提高可读性&#xff0c;我们需要使用不同的名称来声明相同的…

HTML 分组标签与语义化应用:合理使用 <div>、<span> 和基础语义容器

文章目录 1. `<div>` 标签特点用途示例2. `<span>` 标签特点用途示例3. `<fieldset>` 标签特点用途示例4. `<section>` 标签特点用途示例5. `<article>` 标签特点用途示例总结HTML中的分组(容器)标签用于结构化内容,将页面元素组织成逻辑区域…

关于武汉芯景科技有限公司的马达驱动芯片AT6237开发指南(兼容DRV8837)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 逻辑功能

Android View

前面我们了解了Android四大组件的工作流程&#xff0c;Android中还存在一个和四大组件地位相同的概念&#xff1a;View&#xff0c;用于向用户页面展示内容。我们经常使用的TextView、Button、ImageView控件等都继承于它&#xff0c;也会自定义View实现自定义效果。View类源码内…

谷歌插件开发学习指南

什么是谷歌插件 谷歌插件&#xff08;Chrome Extension&#xff09;是为谷歌浏览器&#xff08;Chrome&#xff09;开发的小程序&#xff0c;旨在增强浏览器的功能或用户体验。它们可以通过添加工具栏按钮、修改网页内容、集成其他服务等方式&#xff0c;实现各种功能&#xf…

linux命令行的艺术

文章目录 前言基础日常使用文件及数据处理系统调试单行脚本冷门但有用仅限 OS X 系统仅限 Windows 系统在 Windows 下获取 Unix 工具实用 Windows 命令行工具Cygwin 技巧 更多资源免责声明 熟练使用命令行是一种常常被忽视&#xff0c;或被认为难以掌握的技能&#xff0c;但实际…

Puppeteer 与浏览器版本兼容性:自动化测试的最佳实践

Puppeteer 支持的浏览器版本映射&#xff1a;从 v20.0.0 到 v23.6.0 自 Puppeteer v20.0.0 起&#xff0c;这个强大的自动化库开始支持与 Chrome 浏览器的无头模式和有头模式共享相同代码路径&#xff0c;为自动化测试带来了更多便利。从 v23.0.0 开始&#xff0c;Puppeteer 进…

知识管理新选择!本地大模型助手“知我AI”全功能解析

抖知书老师推荐&#xff1a; 随着人工智能技术的飞速发展&#xff0c;本地大模型知识管理工具逐渐成为提高工作效率的利器。今天&#xff0c;我要向大家介绍一款名为**“知我AI”**的本地知识管理助手&#xff0c;它以其独特的功能和优势&#xff0c;正在成为众多专业人士的新…

Banana Pi BPI-R3路由器开发板运行 OrayOS物联网系统

近日&#xff0c;Banana PI开发板宣布与贝锐达成战略合作&#xff0c;贝锐OrayOS现已成功适配Banana PI的BPI-R3型号&#xff0c;并计划进一步扩展硬件支持&#xff0c;包括目前Banana PI热销的BPI-R4、BPI-R3 Mini等更多型号。这一合作为用户提供了更广泛的开发板选择&#xf…

No.24 笔记 | WEB安全 - 任意文件包含漏洞 part 6

在 Web 安全领域中&#xff0c;任意文件包含漏洞是一种较为常见且具有潜在危险性的漏洞类型。本文将详细介绍任意文件包含漏洞的概念、原理、分类、利用方法以及防护措施&#xff0c;帮助新手小白更好地理解和防范这一漏洞。&#x1f603; 一、概念 包含的定义 开发人员为了提…

森利威尔SL2516D 耐压60V内置5V功率MOS 支持PWM LED恒流驱动器芯片

一、基本特性 型号&#xff1a;SL2516D封装&#xff1a;ESOP8工作频率&#xff1a;140kHz驱动MOS管&#xff1a;内置 二、电气特性 输入电压范围&#xff1a;8V~100V&#xff08;注意&#xff0c;虽然问题中提到耐压60V&#xff0c;但根据官方信息&#xff0c;其实际耐压范围…

Vscode配置CC++编程环境的使用体验优化和补充说明

文章目录 快速编译运行&#x1f47a;code runner插件方案Code Runner Configuration 直接配置 相关指令和快捷键默认task配置和取消默认 配置文件补充介绍(可选 推荐阅读)&#x1f60a;使用vscode预置变量和环境变量环境变量的使用使用环境变量的好处环境变量可能引起的问题 检…

Linux中rpm包和yum仓库介绍及入门配置

rpm包概述 RPM Package Manager,RPM包管理器 由红帽公司提出&#xff0c;适用于Rocky Linux、Redhat、SUSE等系列操作系统 建立集中数据库&#xff0c;记录软件包安装/卸载等变化信息&#xff0c;分析软件包依赖关系 RPM包 文件名特征 软件名-版本信息.操作系统.硬件架/构.r…