美文网首页React
2、前端页面如何优雅的显示PDF(上):渲染页面

2、前端页面如何优雅的显示PDF(上):渲染页面

作者: 编程琐事 | 来源:发表于2020-04-09 22:49 被阅读0次

    推荐阅读

    准备工作

    1. 创建 react 项目:
    create-react-app
    
    1. 在项目中添加 pdf.js 依赖
    npm install pdfjs-dist || yarn add pdfjs-dist
    

    使用 pdfjs-dist

    关键的两个文件

    • pdf.js
    • pdf.worker.js

    如何使用

    import pdfjs from 'pdfjs-dist';
    import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
    pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
    

    这两个文件包含了获取、解析和展示PDF文档的方法,但是解析和渲染PDF需要较长的时间,可能会阻塞其它JS代码的运行。
    为解决该问题,pdf.js依赖了HTML5引入的Web Workers——通过从主线程中移除大量CPU操作(如解析和渲染)来提升性能。

    PDF.js的API都会返回一个Promise,使得我们可以优雅的处理异步操作。但是文档甚少,只能查找源码,浏览 github

    ++题外话:在看别人写的pdf渲染的项目使用 pdfjs-dist 的时候 这么写的++

     pdfjs.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.js');
    

    通过 required 引入 pdf.worker 但是使用 create-react-app 创建的 react 项目在使用的时候不能够直接使用 required,如果这么使用会报这个错
    [图片上传失败...(https://pic2.zhimg.com/80/v2-75bac6b27ae24f93cfc519c24f2c8e9f_1440w.jpg)]

    查看源码就能够定位到问题原因:他的接受的必须是字符串

    # 位置 pdf.js/src/display/worker_options.js Lines 27 to 34 in 4fe9260
    /** 
      * A string containing the path and filename of the worker file. 
      * 
      * NOTE: The `workerSrc` option should always be set, in order to prevent any 
      *       issues when using the PDF.js library. 
      * @var {string} 
      */ 
     GlobalWorkerOptions.workerSrc = 
    

    同样的可以使用 CND 的方式解决这个问题

    pdfjs.GlobalWorkerOptions.workerSrc = "https://cdn.bootcss.com/pdf.js/2.2.228/pdf.worker.js";
    

    渲染

    1. 创建 canvas 以便于渲染pdf
    const canvasRef = useRef(null)
    
    <canvas
        ref={canvasRef}
        width={window.innerWidth}
        height={window.innerHeight}
    />
    
    1. 添加渲染PDF的 js 代码
    # 读取 PDF 文件
    const loadingTask = pdfjs.getDocument(url);
    
    # 获得到 PDF 对象
    const pdf = await loadingTask.promise;
    
    const firstPageNumber = 1;
    
    # 读取到页面信息
    const page = await pdf.getPage(firstPageNumber);
    
    # 设置页面缩放
    const scale = 1;
    const viewport = page.getViewport({scale: scale});
    
    # 以下写法清晰度更高
    # const devicePixelRatio = window.devicePixelRatio;
    # const viewport = page.getViewport({scale: scale * devicePixelRatio});
    
    
    // Prepare canvas using PDF page dimensions
    const canvas = canvasRef.current;
    
    const context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    
    // Render PDF page into canvas context
    const renderContext = {
        canvasContext: context,
        viewport: viewport
    };
    const renderTask = page.render(renderContext);
    

    这样PDF就渲染到刚才我们写的canvas中,但是这段代码只能渲染第一页,通过改变 firstPageNumber 渲染不同的页面。

    getDocument():用于异步获取PDf文档,发送多个Ajax请求以块的形式下载文档。它返回一个Promise,该Promise的成功回调传递一个对象,该对象包含PDF文档的信息,该回调中的代码将在完成PDf文档获取时执行。
    
    getPage():用于获取PDF文档中的各个页面。
    
    getViewport():针对提供的展示比例,返回PDf文档的页面尺寸。
    
    render():渲染PDF。
    

    这也写只能满足简单的翻页需求,如果增加别的需求,放大缩小,文本复制,就不能改满足。我们下节来编写如何能够==文本复制==。

    源码地址:https://github.com/LiuSandy/react-pdf-render

    相关文章

      网友评论

        本文标题:2、前端页面如何优雅的显示PDF(上):渲染页面

        本文链接:https://www.haomeiwen.com/subject/utjkmhtx.html