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 相关文章推荐
jQuery 页面载入进度条实现代码
Feb 08 Javascript
JavaScript中OnLoad几种使用方法
Dec 15 Javascript
javascript 拷贝节点cloneNode()使用介绍
Apr 03 Javascript
node.js WEB开发中图片验证码的实现方法
Jun 03 Javascript
Linux下编译安装php libevent扩展实例
Feb 14 Javascript
BootStrap文件上传样式超好看【持续更新】
May 10 Javascript
详谈jQuery中的一些正则匹配表达式
Mar 08 Javascript
AngularJs 延时器、计时器实例代码
Sep 16 Javascript
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
Sep 04 Javascript
使用ng-packagr打包Angular的方法示例
Sep 21 Javascript
vue中beforeRouteLeave实现页面回退不刷新的示例代码
Nov 01 Javascript
Vue通过getAction的finally来最大程度避免影响主数据呈现问题
Apr 24 Javascript
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
WinXP + Apache +PHP5 + MySQL + phpMyAdmin安装全功略
2006/07/09 PHP
php5数字型字符串加解密代码
2008/04/24 PHP
php中使用Imagick实现图像直方图的实现代码
2011/08/30 PHP
php中将汉字转换成拼音的函数代码
2012/09/08 PHP
php中判断数组是一维,二维,还是多维的解决方法
2013/05/04 PHP
PHP中copy on write写时复制机制介绍
2014/05/13 PHP
字符串长度函数strlen和mb_strlen的区别示例介绍
2014/09/09 PHP
PHP+jQuery+Ajax实现分页效果 jPaginate插件的应用
2015/10/09 PHP
PHP邮件群发机实现代码
2016/02/16 PHP
jQuery前台数据获取实现代码
2011/03/16 Javascript
表格单元格交错着色实现思路及代码
2013/04/01 Javascript
JavaScript声明变量时为什么要加var关键字
2014/09/29 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
2015/09/19 Javascript
VueJs监听window.resize方法示例
2018/01/17 Javascript
vue页面加载闪烁问题的解决方法
2018/03/28 Javascript
Puppet的一些技巧
2018/09/17 Javascript
小程序如何获取多个formId实现详解
2019/09/20 Javascript
javascript实现摄像头拍照预览
2019/09/30 Javascript
使用js实现单链解决前端队列问题的方法
2020/02/03 Javascript
[23:21]Ti4 冒泡赛第二轮DK vs C9 2
2014/07/14 DOTA
selenium3+python3环境搭建教程图解
2018/12/07 Python
python 遍历列表提取下标和值的实例
2018/12/25 Python
Python如何调用外部系统命令
2019/08/07 Python
python学习将数据写入文件并保存方法
2020/06/07 Python
详解python logging日志传输
2020/07/01 Python
使用pygame实现垃圾分类小游戏功能(已获校级二等奖)
2020/07/23 Python
一家专门做特卖的网站:唯品会
2016/10/09 全球购物
Funko官方商店:源自美国,畅销全球搪胶收藏玩偶
2018/09/15 全球购物
司机辞职报告范文
2014/01/20 职场文书
《童趣》教学反思
2014/02/19 职场文书
车间机修工岗位职责
2014/02/28 职场文书
公司任命书模板
2014/06/06 职场文书
小组口号大全
2014/06/09 职场文书
公司合并协议书范本
2014/09/30 职场文书
2016年大学生暑期社会实践活动总结
2016/04/06 职场文书
关于党风廉政建设宣传教育月的活动总结!
2019/08/08 职场文书