PDF.js实现个性化PDF渲染(文本复制)

我肥来啦??。看到Redux教程突破3w的浏览量,小窃喜,很高兴自己的文章能够帮助到大家。

这次重返,依然带给大家一个小指南,也是最近工作中遇到的一个小case。

前不久,产品经理提出要在界面上优雅地展示PDF文档,当即就有了两种实现方式:

实现方式一
使用embed标记来使用浏览器自带的pdf工具。

这种实现方式优缺点都很明显:
优点:自带“打印”,“搜索”,“翻页”等功能,强大且实现方便。
缺点:不同浏览器的pdf工具样式不一,且无法满足个性化需求,比如:禁止打印,下载等。

我们的产品经理是挑剔的??,于是...

实现方式二
使用Mozilla的PDF.js,自定义展示PDF。

下面我们就细致讲述一下使用PDF.js过程中遇到的问题。主要包括:

  • 基础功能集成
  • 使用Text-Layers渲染

什么是PDF.JS

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

基础功能集成

1??引用

首先,引用PDF.js就遇到了问题,官网中提到通过CDN引用或者下载源码至本地。
而我们并不想污染我们的index.html并且希望可以对每一个引用的框架有统一的版本管理。于是,我们搜寻到一个包:pdfjs-dist

通过npm install pdfjs-dist,我们引入了PDF.js。

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

  • pdf.js
  • pdf.worker.js

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

如果使用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,使得我们可以优雅的处理异步操作。

2??使用

首先,我们需要在HTML中添加<canvas>元素以渲染PDF:

<canvas id="pdf-canvas"></canvas>

然后添加渲染PDF的js代码:

var url = ‘Helloworld.pdf‘;

PDFJS.getDocument(url).then((pdf) => {
    return pdf.getPage(1);
}).then((page) => {
    // 设置展示比例
    var scale = 1.5;
    // 获取pdf尺寸
    var viewport = page.getViewport(scale);
    // 获取需要渲染的元素
    var canvas = document.getElementById(‘pdf-canvas‘);
    var context = canvas.getContext(‘2d‘);
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    var renderContext = {
        canvasContext: context,
        viewport: viewport
    };

    page.render(renderContext);
});

现在,PDF已经成功渲染在界面上了。我们来分析一下使用到的函数:

getDocument():用于异步获取PDf文档,发送多个Ajax请求以块的形式下载文档。它返回一个Promise,该Promise的成功回调传递一个对象,该对象包含PDF文档的信息,该回调中的代码将在完成PDf文档获取时执行。

getPage():用于获取PDF文档中的各个页面。

getViewport():针对提供的展示比例,返回PDf文档的页面尺寸。

render():渲染PDF。

到这里,基本功能告一段落了。
满心欢喜准备上线的时候,产品经理提出了另一个需求:文本复制。
然鹅。。。翻了好几遍官方文档,也没有找到文本复制的方法,并且stackoverflow上有很多类似的问题。
在不断的尝试下,我们发现了Text-Layer

使用Text-Layers渲染

PDF.js支持在使用Canvas渲染的PDF页面上渲染文本图层。然而,这个功能需要用到额外的两个文件:text_layer_builder.jstext_layer_builder.css。我们可以在GitHub的repo中获取到。

如果是使用npm,则需要做如下引用:

import { TextLayerBuilder } from ‘pdfjs-dist/web/pdf_viewer‘;
import ‘pdfjs-dist/web/pdf_viewer.css‘;

现在,我们开始实现文本复制功能。

首先,创建渲染需要用到DOM节点:

<div id="container"></div>

div#container为最外层节点,在该div中,我们会为PDF的每个页面创建自己的div,在每个页面的div中,都会有Canvas元素。

接着,我们修改JS代码:

var container, pageDiv;

function getPDF(url) {
    PDFJS.getDocument(url).then((pdf) => {
        pdfDoc = pdf;
        container = document.getElementById(‘container‘);
        for (var i = 1; i<= pdf.numPages; i++) {
            renderPDF(i);
        }
    })
}

function renderPDF(num) {
    pdf.getPage(num).then((page) => {
        var scale = 1.5;
        var viewport = page.getViewport(scale);
        pageDiv = document.createElement(‘div‘);
        pageDiv.setAttribute(‘id‘, ‘page-‘ + (page.pageIndex + 1));
        pageDiv.setAttribute(‘style‘, ‘position: relative‘);
        container.appendChild(pageDiv);
        var canvas = document.createElement(‘canvas‘);
        pageDiv.appendChild(canvas);
        var context = canvas.getContext(‘2d‘);
        canvas.height = viewport.height;
        canvas.width = view.width;

        var renderContext = {
            canvasContext: context,
            viewport: viewport
        };

        page.render(renderContext);
    });
}

以上代码只是实现了多页渲染,接下来,开始渲染文本图层。我们需要将page.render(renderContext)修改为以下代码:

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实例
    var textLayer = new TextLayerBuilder({
        textLayerDiv: textLayerDiv,
        pageIndex: page.pageIndex,
        viewport: viewport
    });

    textLayer.setTextContent(textContent);

    textLayer.render();
});

我们依旧来讲解以下用到的几个关键函数:

page.render():该函数返回一个当PDF页面成功渲染到界面上时解析的promise,我们可以使用成功回调来渲染文本图层。

page.getTextContent():该函数的成功回调会返回PDF页面上的文本片段。

TextLayerBuilder:该类的实例有两个重要的方法。setTextContent()用于设置page.getTextContent()函数返回的文本片段;render()用于渲染文本图层。

Bingo??!通过以上改造,文本复制功能就实现了。官方文档上可没有这个小技巧哦。

PDF.js是一个很棒的工具,但无奈文档写的较为精简,需要开发人员不断探索PDF.js的强大功能。

如果这篇文章有帮助到您,记得点赞咯??!

原文地址:https://www.cnblogs.com/pangguoming/p/10341277.html

时间: 2024-10-09 01:46:20

PDF.js实现个性化PDF渲染(文本复制)的相关文章

pdf.js浏览中文pdf乱码的问题解决

由于项目中需要支持移动设备在线浏览pdf,苹果还好,天生支持,但是安卓中就不行了,需要第三方组件的支持. 这里就找到了pdf.js,由于pdf数据太多,开始的时候没法一一测试,所以随便测试打开了几篇没问题后就直接上线了. 但是后面就悲剧了,偶然收到反馈,有些pdf无法正常浏览,此为写本文的原因. 具体的现像 查找问题过程 一.用火狐(火狐解析pdf是用的pdf.js)来直接打开这篇pdf,发现居然是对的,那怀疑用的pdf.js不是最新的?下了一个,问题依旧.问题陷入僵局. 二.漫无目的,打开浏览

使用PDF.JS在线查看PDF

过程简单粗暴. 第一步:下载源码https://github.com/mozilla/pdf.js 第二步:将源码拷贝进项目中,可以新建一个PDFShow文件夹存放代码 第三步:修改viewer.js var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf'  里面是PDF的路径 修改为:var DEFAULT_URL = ''; 发布IIS后访问localhost:8080/PDFShow/web/viewer.html?file=09.pd

java 使用 pdf.js 在线查看 pdf 文档

1. 下载对应的 pdf.js 文件: 推荐地址:             https://github.com/mozilla/pdf.js/            http://mozilla.github.io/pdf.js/ 2. 下载完成后打开对应的 viewer.js 文件. 可以看到,默认打开的是 compressed.tracemonkey-pldi-09.pd f文件,如果后面我们需要打开我们指定的地址,于是清空默认地址. 3. 这样,我们就可以使用传递 file 形参来动态指

[pdf.js]预览pdf时,中文名称乱码的问题

在项目中使用了pdf.js的方式预览pdf,但针对中文名称的时候会出现乱码,导致找不到该文件而出现错误. 解决办法 <script src="viewer.js" charset="gb2312"></script> 结果

pdf.js实现图片在线预览

项目需求 前段时间项目中遇到了一个模块,是关于在线预览word文档(PDF文件)的,所以,找了很多插件,例如,pdf.js,pdfobject.js框架,但是pdfobject.js框架对于IE浏览器不兼容,所以,选择了使用pdf.js,这里记录一下,以后使用的时候好查找,也希望可以帮助有需要的人. word文件转pdf文件 首先需要将指定的word文档转为pdf文件,方法有很多,这里不介绍,有需要的童鞋可以去网上下载即可.我这里用的是OpenOffice,版本是4.1.6,使用很简单,下载好了

pdf转为html查看pdf.js

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

pdf.js 使用实例

pdf.js可以实现在html下直接浏览pdf文档,是一款开源的pdf文档读取解析插件 pdf.js主要包含两个库文件,一个pdf.js和一个pdf.worker.js,,一个负责API解析,一个负责核心解析 下载地址:http://cnblogs.com/files/xiangliuyunyang/build.zip 两个主要demo 1.点击连接读取第一页的pdf文档:http://www.51purse.com/pdf/web/demo1.html(此处没有自己上传) 2.点击连接,选择需

pdf.js使用教程

pdf.js框架的魅力所在,为其为HTML5实现的,无需任何本地支持,而且对浏览器的兼容性也是比较好,要求只有一个:浏览器支持HTML5就好了!(不过对于低版本的IE,就只能节哀了!) 据说IE9以上是OK的,因为我本地是IE11,所以我只在IE11上测试过,是通过的(当然火狐,360,我也测了一下,是可以的). 因为项目开发需要,在线展示PDF,而且要兼容IE,所以就选择了pdf.js,但是网上对他的教程很少,我花了一天时间才搞定,回头看了一下,也没有想象中那么困难,所以决定写一篇博客,以便大

pdf.js的使用

关于pdf.js的使用,我现在只会一点点 首先先下载pdf.js,可以下载官方的 而后是将这个文件夹复制到项目中,我使用的是idea,我将它放在webapp下. 而后再编写一个jsp文件 <%-- Created by IntelliJ IDEA. User: Administrator Date: 2018/12/5 0005 Time: 下午 6:49 To change this template use File | Settings | File Templates. --%> &l