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 相关文章推荐
用于节点操作的API,颠覆原生操作HTML DOM节点的API
Dec 11 Javascript
JQuery中的$.getJSON 使用说明
Mar 10 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
Jul 18 Javascript
jquery中的$(document).ready()使用小结
Feb 14 Javascript
js淡入淡出的图片轮播效果代码分享
Aug 24 Javascript
js实现动态加载脚本的方法实例汇总
Nov 02 Javascript
javascript实现抽奖程序的简单实例
Jun 07 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
Jun 21 Javascript
js实现百度地图定位于地址逆解析,显示自己当前的地理位置
Dec 08 Javascript
JavaScript监听触摸事件代码实例
Dec 30 Javascript
微信小程序scroll-view实现滚动到锚点左侧导航栏点餐功能(点击种类,滚动到锚点)
Jun 11 Javascript
一文帮你理解PReact10.5.13源码
Apr 03 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
wordpress之wp-settings.php
2007/08/17 PHP
写出高质量的PHP程序
2012/02/04 PHP
php如何实现只替换一次或N次
2015/10/29 PHP
PHP中危险的file_put_contents函数详解
2017/11/04 PHP
Extjs gridpanel 出现横向滚动条问题的解决方法
2011/07/04 Javascript
jQuery aminate方法定位到页面具体位置
2013/12/26 Javascript
js实现带关闭按钮始终显示在网页最底部工具条的方法
2015/03/02 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
JavaScript日期对象(Date)基本用法示例
2017/01/18 Javascript
谈谈对vue响应式数据更新的误解
2017/08/01 Javascript
jQuery实现新闻播报滚动及淡入淡出效果示例
2018/03/23 jQuery
深入浅析JS中的严格模式
2018/06/04 Javascript
详解写好JS条件语句的5条守则
2019/02/28 Javascript
微信小程序云开发之云函数详解
2019/05/16 Javascript
vue elementui el-form rules动态验证的实例代码详解
2019/05/23 Javascript
layui的布局和表格的渲染以及动态生成表格的方法
2019/09/18 Javascript
微信小程序 button样式设置为图片的方法
2020/06/19 Javascript
[05:01]3.19DOTA2发布会 我们都是刀塔人
2014/03/25 DOTA
简单谈谈python中的Queue与多进程
2016/08/25 Python
Java实现的执行python脚本工具类示例【使用jython.jar】
2018/03/29 Python
python调用tcpdump抓包过滤的方法
2018/07/18 Python
在pandas多重索引multiIndex中选定指定索引的行方法
2018/11/16 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
Python3.6中Twisted模块安装的问题与解决
2019/04/15 Python
Python项目 基于Scapy实现SYN泛洪攻击的方法
2019/07/23 Python
大学生秋游活动方案
2014/02/17 职场文书
质量安全标语
2014/06/07 职场文书
物理系毕业生自荐书
2014/06/13 职场文书
大三学年自我鉴定范文(3篇)
2014/09/28 职场文书
学生检讨书怎么写
2014/10/09 职场文书
文案策划岗位职责
2015/02/11 职场文书
教师培训学习心得体会
2016/01/21 职场文书
python 统计代码耗时的几种方法分享
2021/04/02 Python
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
2021/06/26 MySQL
德劲DE1102数字调谐收音机机评
2022/04/07 无线电
Redis+AOP+自定义注解实现限流
2022/06/28 Redis