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 相关文章推荐
javascript[js]获取url参数的代码
Oct 17 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
May 07 Javascript
jquery实现公告翻滚效果
Feb 27 Javascript
AngularJS学习笔记之依赖注入详解
May 16 Javascript
JavaScript实战之带收放动画效果的导航菜单
Aug 16 Javascript
ES6中Iterator与for..of..遍历用法分析
Mar 31 Javascript
从parcel.js打包出错到选择nvm的全部过程
Jan 23 Javascript
微信小程序仿微信运动步数排行(交互)
Jul 13 Javascript
react 中父组件与子组件双向绑定问题
May 20 Javascript
Node.js 在本地生成日志文件的方法
Feb 07 Javascript
谈一谈vue请求数据放在created好还是mounted里好
Jul 27 Javascript
vue 扩展现有组件的操作
Aug 14 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
overlord人气高涨,却被菲利普频繁举报,第四季很难在国内上映
2020/05/06 日漫
php数据库连接
2006/10/09 PHP
用PHP动态生成虚拟现实VRML网页
2006/10/09 PHP
Yii实现多按钮保存与提交的方法
2014/12/03 PHP
10个简化PHP开发的工具
2014/12/25 PHP
PHP自定义多进制的方法
2016/11/03 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
Aster vs Newbee BO3 第二场2.18
2021/03/10 DOTA
extjs_02_grid显示本地数据、显示跨域数据
2014/06/23 Javascript
详解javascript事件冒泡
2016/01/09 Javascript
微信小程序实现漂亮的弹窗效果
2020/05/26 Javascript
js模拟实现烟花特效
2020/03/10 Javascript
微信小程序整个页面的自动适应布局的实现
2020/07/12 Javascript
JavaScript TAB栏切换效果的示例
2020/11/05 Javascript
基于vue项目设置resolves.alias: '@'路径并适配webstorm
2020/12/02 Vue.js
[04:13]2014DOTA2国际邀请赛 专访DC目前形势不容乐观
2014/07/12 DOTA
[07:43]《辉夜杯》公开赛晋级外卡赛战队—TRG训练生活探秘
2015/12/11 DOTA
[03:17]史诗级大片应援2018DOTA2国际邀请赛 致敬每一位坚守遗迹的勇士
2018/07/20 DOTA
Python保存MongoDB上的文件到本地的方法
2016/03/16 Python
python使用turtle库绘制时钟
2020/03/25 Python
python3基于TCP实现CS架构文件传输
2018/07/28 Python
使用pandas 将DataFrame转化成dict
2019/12/10 Python
html5的localstorage详解
2017/05/09 HTML / CSS
Html5剪切板功能的实现代码
2018/06/29 HTML / CSS
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
介绍一下.net和Java的特点和区别
2012/09/26 面试题
英语教师岗位职责
2014/03/16 职场文书
党员国庆节演讲稿范文2014
2014/09/21 职场文书
未婚证明书模板
2014/10/08 职场文书
退学证明范本3篇
2014/10/29 职场文书
幼儿教师个人总结
2015/02/05 职场文书
勇敢的心观后感
2015/06/09 职场文书
小学教师教学随笔
2015/08/14 职场文书
2016元旦晚会主持词开场白和结束语
2015/12/04 职场文书
利用python做表格数据处理
2021/04/13 Python
手把手教你从零开始react+antd搭建项目
2021/06/03 Javascript