vue使用pdfjs显示PDF可复制的实现方法


Posted in Javascript onDecember 14, 2018

pdf显示的方法

方法一

使用embed标记来使用浏览器自带的pdf工具。

这种实现方式优缺点都很明显:

优点:自带“打印”,“搜索”,“翻页”等功能,强大且实现方便。

缺点:不同浏览器的pdf工具样式不一,且无法满足个性化需求,比如:禁止打印,下载等。

方法二

使用Mozilla的PDF.js,自定义展示PDF。

  • 基础功能集成
  • 使用Text-Layers渲染(可实现pdf内容复制)

什么是PDF.JS

PDF.js是基于HTML5技术构建的,用于展示可移植文档格式的文件(PDF),它可以在现代浏览器中使用且无需安装任何第三方插件。

安装:

npm install pdfjs-dist

基础功能有两个必须引用的文件:

  • pdf.js
  • pdf.worker.js

如果使用CDN的方式,直接引用如下对应文件即可:

  • https://mozilla.github.io/pdf.js/build/pdf.js
  • https://mozilla.github.io/pdf.js/build/pdf.worker.js

如果使用npm的方式,则在需要使用PDF.js的文件中如下引用:

import PDFJS from 'pdfjs-dist';

PDFJS.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.js';

这两个文件包含了获取、解析和展示PDF文档的方法,但是解析和渲染PDF需要较长的时间,可能会阻塞其它JS代码的运行。

为解决该问题,pdf.js依赖了HTML5引入的Web Workers——通过从主线程中移除大量CPU操作(如解析和渲染)来提升性能。

PDF.js的API都会返回一个Promise,使得我们可以优雅的处理异步操作。

使用

本文章只介绍在vue中的使用, 下面是自己写的展示pdf的组件可以直接拿去用

注:具体解释请看下面代码中的注释

<template>
  <!--<button @click="scalBig">放大</button>-->
  <!--<button @click="scalSmall">缩小</button>-->
  <!--<p>页码:{{`${pageNo}/${totals.length}`}}</p>-->
  <div class="drag-box" id="dragBox" @scroll="scrollfun($event)">
   <el-scrollbar style="height: 100%;overflow-y: hidden;">
   <div class="wrapper" id="pdf-container">
    <div v-for="item in totals" :id="`page-${item}`" :key="item" class="pdf-box">
     <canvas :id="'canvas-pdf-' + item" class="canvas-pdf"></canvas>
    </div>
   </div>
   </el-scrollbar>
  </div>
</template>

<script>
import PDFJS from 'pdfjs-dist'
import { TextLayerBuilder } from 'pdfjs-dist/web/pdf_viewer'
import 'pdfjs-dist/web/pdf_viewer.css'
export default {
 name: 'showPdf',
 props: ['pdfUrl'],
 data () {
  return {
   scale: 1.4,
   totals: [],
   pageNo: 1,
   viewHeight: 0
  }
 },
 mounted () {
  this.renderPdf(this.scale)
 },
 watch: {
  scale (val) {
   this.totals = []
   this.renderPdf(val)
  }
 },
 methods: {
  renderPdf (scale) {
   PDFJS.workerSrc = require('pdfjs-dist/build/pdf.worker.min')
   // 当 PDF 地址为跨域时,pdf 应该已流的形式传输,否则会出现pdf损坏无法展示
   PDFJS.getDocument(this.pdfUrl).then(pdf => {
    // 得到PDF的总的页数
    let totalPage = pdf.numPages
    let idName = 'canvas-pdf-'
    // 根据总的页数创建相同数量的canvas
    this.createCanvas(totalPage, idName)
    for (let i = 1; i <= totalPage; i++) {
     pdf.getPage(i).then((page) => {
      let pageDiv = document.getElementById(`page-${i}`)
      let viewport = page.getViewport(scale)
      let canvas = document.getElementById(idName + i)
      let context = canvas.getContext('2d')
      canvas.height = viewport.height
      canvas.width = viewport.width
      this.viewHeight = viewport.height
      let renderContext = {
       canvasContext: context,
       viewport
      }
      // 如果你只是展示pdf而不需要复制pdf内容功能,则可以这样写render
      // page.render(renderContext) 如果你需要复制则像下面那样写利用text-layer
      page.render(renderContext).then(() => {
       return page.getTextContent()
      }).then((textContent) => {
       // 创建文本图层div
       const textLayerDiv = document.createElement('div')
       textLayerDiv.setAttribute('class', 'textLayer')
       // 将文本图层div添加至每页pdf的div中
       pageDiv.appendChild(textLayerDiv)
       // 创建新的TextLayerBuilder实例
       let textLayer = new TextLayerBuilder({
        textLayerDiv: textLayerDiv,
        pageIndex: page.pageIndex,
        viewport: viewport
       })
       textLayer.setTextContent(textContent)
       textLayer.render()
      })
     })
    }
   })
  },
  createCanvas (totalPages) {
   for (let i = 1; i <= totalPages; i++) {
    this.totals.push(i)
   }
  },
  // 分页
  scrollfun (e) {
   let scrollTop = e.target.scrollTop
   if (scrollTop === 0) {
    this.pageNo = 1
   } else {
    this.pageNo = Math.ceil(scrollTop / this.viewHeight)
   }
  },
  // 放大
  scalBig () {
   this.scale = this.scale + 0.1
  },
  // 缩小
  scalSmall () {
   if (this.scale > 1.2) {
    this.scale = this.scale - 0.1
   }
  }
 }
}
</script>

<style scoped lang="scss">
 .drag-box {
  height: 800px;
 }
 .pdf-box {
  position: relative;
 }
 .el-scrollbar__wrap {
  overflow-x: hidden;
 }
</style>

pdf.js实现展示和复制PDF内容介绍到这里,后续会继续更新实现下载、打印等功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JSON 学习之完全手册 图文
May 29 Javascript
JavaScript 字符串与数组转换函数[不用split与join]
Dec 13 Javascript
js猜数字小游戏的简单实现代码
Jul 02 Javascript
JS获取键盘上任意按键的值(实例代码)
Nov 12 Javascript
Javascript监视变量变化的方法
Jun 09 Javascript
requireJS模块化实现返回顶部功能的方法详解
Oct 16 Javascript
React Native悬浮按钮组件的示例代码
Apr 05 Javascript
angular实现页面打印局部功能的思考与方法
Apr 13 Javascript
小程序ios音频播放没声音问题的解决
Jul 11 Javascript
浅谈vue方法内的方法使用this的问题
Sep 15 Javascript
详解vue的数据劫持以及操作数组的坑
Apr 18 Javascript
jQuery实现带进度条的轮播图
Sep 13 jQuery
antd Upload 文件上传的示例代码
Dec 14 #Javascript
Vue源码解析之Template转化为AST的实现方法
Dec 14 #Javascript
JavaScript模板引擎实现原理实例详解
Dec 14 #Javascript
Angular2 自定义表单验证器的实现方法
Dec 14 #Javascript
JavaScript模板引擎应用场景及实现原理详解
Dec 14 #Javascript
详解React 服务端渲染方案完美的解决方案
Dec 14 #Javascript
JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例
Dec 14 #Javascript
You might like
全国FM电台频率大全 - 23 四川省
2020/03/11 无线电
解析二进制流接口应用实例 pack、unpack、ord 函数使用方法
2013/06/18 PHP
浅析Yii中使用RBAC的完全指南(用户角色权限控制)
2013/06/20 PHP
php如何解决无法上传大于8M的文件问题
2014/03/10 PHP
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
2014/07/22 PHP
Linux php 中文乱码的快速解决方法
2016/05/13 PHP
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
两个比较有用的Javascript工具函数代码
2010/02/17 Javascript
关于JS字符串函数String.replace()
2013/04/07 Javascript
JS图片无缝滚动(简单利于使用)
2013/06/17 Javascript
Jquery选择子控件&quot;大于号&quot;和&quot; &quot;区别介绍及使用示例
2013/06/25 Javascript
用jquery存取照片的具体实现方法
2013/06/30 Javascript
js正则表达式的使用详解
2013/07/09 Javascript
js仿百度贴吧验证码特效实例代码
2014/01/16 Javascript
Node.js实现在目录中查找某个字符串及所在文件
2014/09/03 Javascript
初探nodeJS
2017/01/24 NodeJs
JavaScript限定范围拖拽及自定义滚动条应用(3)
2017/05/17 Javascript
vue实现密码显示隐藏切换功能
2018/02/23 Javascript
jQuery 隐藏/显示效果函数用法实例分析
2020/05/20 jQuery
python函数参数*args**kwargs用法实例
2013/12/04 Python
Python中用于去除空格的三个函数的使用小结
2015/04/07 Python
Python实现方便使用的级联进度信息实例
2015/05/05 Python
spyder常用快捷键(分享)
2017/07/19 Python
Python日志模块logging基本用法分析
2018/08/23 Python
python2和python3的输入和输出区别介绍
2018/11/20 Python
详解python持久化文件读写
2019/04/06 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
Pycharm 安装 idea VIM插件的图文教程详解
2020/02/21 Python
python时间序列数据转为timestamp格式的方法
2020/08/03 Python
Python新建项目自动添加介绍和utf-8编码的方法
2020/12/26 Python
美国最好的葡萄酒网上商店:Wine Library
2019/11/02 全球购物
触发器(trigger)的功能都有哪些?写出一个触发器的例子
2012/09/17 面试题
汽车检测与维修个人求职信
2013/09/24 职场文书
学生周末回家住宿长期请假条
2014/02/15 职场文书
工作收入证明范本
2015/06/12 职场文书
2015高中教师个人工作总结
2015/07/21 职场文书