vue+pdf.js预览本地pdf文件(可以复制文本,滚动页码展示)

5 篇文章 0 订阅
1 篇文章 0 订阅

1、安装pdfjs-dist插件,推荐使用2.0.943这个版本

npm install pdfjs-dist@2.0.943

2、页面中引入使用

import PDFJS from 'pdfjs-dist'
// 文本视图,可复制
import { TextLayerBuilder } from 'pdfjs-dist/web/pdf_viewer'
import 'pdfjs-dist/web/pdf_viewer.css'
PDFJS.workerSrc = require('pdfjs-dist/build/pdf.worker.min')

3、页面标签

<div class="pdfContainer">
  <div class="pdfOprate">
    <!-- 当前页码/页码总数 -->
    <span class="pdfCount">
       <span class="pdfPage">{{pdfPage}}</span> / <span class="pdfPageTotal">{{pdfTotalPages}}</span>
    </span>
  </div>
  <!-- pdf视图 -->
  <div class="pdfBody" @scroll="pdfScroll($event)">
    <div id="pdfBox">
      <!-- pdf内容,图片和文本视图 -->
      <!-- <div class="divBox">
        <canvas ></canvas>
        <div class="textLayer"></div>
      </div> -->
    </div>
  </div>
</div>

3、解析pdf,获取pdf所有页数据,使用canvas渲染,并使用TextLayerBuilder创建文本层,可以复制文本信息

// 使用pdf.js加载和显示PDF文件
previewPdf(file){
    var that=this
    const fileReader = new FileReader();
    fileReader.onload = function() {
        const typedArray = new Uint8Array(this.result);
        // 调用pdf.js的API加载PDF文件
        PDFJS.getDocument(typedArray).promise.then(async function(pdf) {
            that.viewPdfObject=pdf
            // 获取PDF的总页数
            const numPages = pdf.numPages;
            // 渲染当前显示页码和总页数
            this.pdfPage=1
            this.pdfTotalPages=numPages
            const pdfBox = document.getElementById("pdfBox");
            // 循环绘制每个页面
            for (let pageNum = 1; pageNum <= numPages; pageNum++) {
              // 获取指定页数据
              let page = await pdf.getPage(pageNum)
              // 获取视图 1是倍率,按照pdf解析出来的原始宽高
              const viewport = page.getViewport(1)
              
              const divBox=document.createElement("div")
              divBox.className="divBox"
              pdfBox.appendChild(divBox)
              const canvasElement=document.createElement("canvas")
              const context = canvasElement.getContext("2d");
              canvasElement.width = viewport.width;
              canvasElement.height = viewport.height;
              divBox.appendChild(canvasElement)

              // 渲染指定页的内容到canvas上
              // 如果你只是展示pdf而不需要复制pdf内容功能,则可以这样写render
              // page.render({canvasContext: context,viewport})
              // 需要复制内容就使用下面的渲染方式
              var textContent=await page.render({
                canvasContext: context,
                viewport
              }).then(() => {
                return page.getTextContent();
              })

              // 创建文本图层div
              const textLayerDiv = document.createElement('div')
              textLayerDiv.className="textLayer"
              textLayerDiv.setAttribute('class', 'textLayer')
              textLayerDiv.setAttribute('style', 'margin:auto;'+'width:'+viewport.width+'px;'+'height:'+viewport.height+'px')
              // 将文本图层div添加至每页pdf的div中
              divBox.appendChild(textLayerDiv)
              // 创建新的TextLayerBuilder实例
              let textLayer = new TextLayerBuilder({
                textLayerDiv: textLayerDiv,
                pageIndex: page.pageIndex,
                viewport: viewport
              })
              textLayer.setTextContent(textContent)
              textLayer.render()
            }
        })
    }
    fileReader.readAsArrayBuffer(file);
},

在渲染pdf数据时,当pdf文件很大渲染量很多时,会导致页面卡住,无法执行其他操作;这涉及到队列优先级问题:
在这里插入图片描述
在这里就是因为微任务导致,所以我们这里渲染pdf任务可以每次渲染完一页后等待一定时间才执行下一页的渲染,空出时间给主线程

// 将渲染pdf的代码休眠一定时间,留给主线程
sleep(time){
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(time)
    }, time)
  })
},
// 创建一个延时队列的任务 主进程会执行渲染队列任务后在执行延时队列任务等待延时,后再创建渲染pdf下一页的微任务(在循环代码的最后使用)
await that.sleep(100)

在滚动时当前是第几页的页码同步更新展示:需要在渲染每页pdf时将每页的高度存起来,以及每页滚动的临界值

// 每页累加的高度
this.scrollHeight=[0]
// 每页滚动切换值的临界滚动距离
this.scrollHalfHeight=[0]
this.heightAll=0
$(".pdfBody canvas").each(function (i) {
	// 滚动到前一页高度的70%,即页码自动更改为下一页
    that.heightAll+=this.height*that.zoom*0.7
    that.scrollHalfHeight.push(that.heightAll)
    that.heightAll+=this.height*that.zoom*0.3
    that.scrollHeight.push(that.heightAll)
})

在滚动时,根据当前滚动距离和每页滚动的临界距离相比较,判断当前是第几页

pdfScroll(e){
  var pdfBody=document.querySelector(".pdfBody")
  for (let i=0;i<this.scrollHeight.length;i++){
    // 在滚动时,根据当前滚动距离和每页滚动的临界距离相比较,判断当前是第几页
    if(pdfBody.scrollTop>=this.scrollHeight[i]&&pdfBody.scrollTop<this.scrollHeight[i+1]){
      if (this.pdfPage!=i+1){
        this.pdfPage=i+1
      }
    }
  }
}

效果如下
在这里插入图片描述

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Vue.js 是一个流行的前端框架,而 Three.js 是一个用于创建 3D 图形的 JavaScript 库。将两者结合起来可以创建出令人惊叹的 3D 应用程序。下面是 vue+three.js 的每步解析: 1. 创建 Vue.js 应用程序 首先,需要创建一个 Vue.js 应用程序。可以使用 Vue CLI 来生成一个新的项目或手动创建一个新的 Vue.js 应用程序。 2. 安装 Three.js 可以使用 npm 包管理器安装 Three.js,也可以直接下载 Three.js 库文件并将其添加到项目中。 3. 在 Vue 组件中引入 Three.js 在 Vue.js 中使用 Three.js 需要将其导入到组件中。可以使用 ES6 的 import 语句来引入 Three.js。 4. 创建场景、相机和渲染器 在 Three.js 中创建 3D 场景需要场景、相机和渲染器。可以在 Vue.js 组件的 mounted 钩子函数中创建它们。 5. 创建 3D 对象 可以使用 Three.js 来创建各种类型的 3D 对象,如立方体、球体、平面等。可以在 Vue.js 组件的 mounted 钩子函数中创建它们。 6. 将 3D 对象添加到场景中 创建 3D 对象后,需要将它们添加到场景中。可以使用场景对象的 add 方法来添加它们。 7. 渲染场景 最后,在 Vue.js 组件的 mounted 钩子函数中使用渲染器对象来渲染场景。 这是一个基本的 vue+three.js 应用程序的步骤。当然,还有很多其他的细节需要注意,如处理用户交互、加载 3D 模型等。但是,掌握了这些基本步骤,就可以开始创建自己的 3D 应用程序了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值