记使用pdf.js过程遇到的坑

最近项目中需要用到js库来渲染pdf文件,调研后发现无论是reach-pdf.js或者是svelte-pdf.js都是在pdf.js基础上做了些许精简,反而功能还不如原始的pdf.js来得全面。但是原始的库几乎没有像样的代码示例,而能搜索到的大多数代码不少都是十几年前的了,在这个过程中踩了不少坑,做个记录,希望对看到的人有所帮助。

使用npm安装pdfjs-dist库(也可以直接下载源码并引入)

npm install pdfjs-dist

导入库

// 网上很多代码都是import xxx from 'pdfjs-dist';
// 而xxx一般都是过期或者不存在的,直接把所有导出为pdfjslib即可
import * as pdfjslib from 'pdfjs-dist';
// 注意需要设置这个参数
pdfjslib.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.js';

单页渲染,多页渲染在下面代码基础上直接添加一个循环即可

let src = 'xxx.pdf';
let pageNum = 1;
let scale_ratio = 1.5;

async function renderPage() {
    const pdf = await pdfjsLib.getDocument(src).promise;
    const page = await pdf.getPage(pageNum);
    const viewport = page.getViewport({ scale: scale_ratio });

    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');

    canvas.height = viewport.height;
    canvas.width = viewport.width;

    const renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    await page.render(renderContext);

  }

注意渲染完的pdf只有图片形式,使用开发者工具看网页的结构只有canvas组件,想要实现文字的选择和复制还需要在上面渲染一层文字层。

// 需要引入样式文件,不然文字不会悬浮在cavas组件上
import 'pdfjs-dist/web/pdf_viewer.css';

async function renderFullPage(){
        const pdf = await pdfjsLib.getDocument(src).promise;

        const pdfContainer = document.createElement('div');
        pdfContainer.style.setProperty('--scale-factor', scale_ratio);

        for (let i=1; i<=pdf.numPages; i++){
            const pageNumber = i;
            const page = await pdf.getPage(pageNumber);

            const viewport = page.getViewport({scale: scale_ratio});

            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');

            canvas.height = viewport.height ;
            canvas.width = viewport.width ;
            
            const renderContext = {
                canvasContext: context,
                viewport: viewport
            };
        
            await page.render(renderContext);

            // canvasWrapper 可加可不加
            const canvasWrapper = document.createElement('div');
            canvasWrapper.className = 'canvasWrapper';
            canvasWrapper.appendChild(canvas);

            const textContent = await page.getTextContent();
            const textLayerDiv = document.createElement('div');
            // 类名严格为:textLayer
            textLayerDiv.className = `textLayer`;

            pdfjsLib.renderTextLayer({
                textContentSource: textContent,
                container: textLayerDiv,
                viewport: viewport,
                textDivs: []
            });
            
            const pageDiv = document.createElement('div');
            pageDiv.className = 'page';
            // 需要设置 position: relative
            // 否则全部文字可能都挤在第一页
            pageDiv.style = "position: relative; margin-bottom:10px";

            pageDiv.appendChild(canvasWrapper);
            pageDiv.appendChild(textLayerDiv);
            
            pdfContainer.appendChild(pageDiv);
            
        }

    }

简单来说就是在渲染完canvas代码之后,再渲染出文字层。有几个注意点:

  1. 需要在开头引入样式表,不然文字层会实际显示在页面中,不会悬浮不会透明;
  2. 需要在外面的组件中设置参数–scale-factor,用于保证图片和文字的位置对应,否则调整了scale_ratio后图片尺寸改变,但是文字层的大小还是不变;
  3. 文字层的类名需要严格设置为textLayer,从开头引入的样式表中可以看到;
  4. 包含canvas和文字层的父组件需要设置style为position: relative,否则多页的文字都会渲染到第一页中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632615.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JUnit5测试用例

1.用Test注解表示为测试方法 2.使用DisplayName定义别名 3.使用Assertions类的断言方法 使用断言&#xff0c;可以判断方法的实际执行结果和预期结果是否一致 assertEqualsassertTureassertNotNullassertAllassertThrows 下图是预期与实际不同时报错图 4.使用BeforeEach注解&…

【原创】java+springboot+mysql企业邮件管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

uniapp微信小程序使用vscode代替HBuilderX开发uniapp微信小程序并且vscode改动代码微信开发者工具能实时更新

前言 最近公司开发新的小程序项目&#xff0c;经调研综合所有人员考虑&#xff0c;用uni-app Vue3tsvite技术栈开发&#xff1b;而官方推荐使用HBuilderX开发&#xff0c;而考虑到目前公司所有前端人员对VsCode更熟悉&#xff0c;故此总结了一下uniapp项目使用vscode代替HBuild…

vue3 + antd-vue@4 a-table单元格合并,rowSpan(行合并),colSpan(列合并)详解, 表头合并详解, 表头自定义详解

一、解释 1、rowSpan 1&#xff09;、行合并 2&#xff09;、当为0时&#xff1a;去掉边框 3&#xff09;、当为1时&#xff1a;不合并 4&#xff09;、大于1的x时&#xff1a;包含当前单元格行合并x个单元格 2、colSpan 1&#xff09;、列合并 2&#xff09;、当为0时&#xf…

C++ 将字符串解析为argc、argv

文章目录 前言一、如何实现&#xff1f;1、实现split2、split双引号3、奇数下标元素加入结果4、偶数下标元素split空格 二、完整代码三、使用示例1、解析命令行2、构造argc、argv 总结 前言 一般开启子进程的时候&#xff0c;需要传参数&#xff0c;通常直接传输命令行字符串&…

SQL使用Groupby分组后,选择每个分组某个值最大的那一行

思路是&#xff1a; 先定位分组后某个值最大的值是多少根据值去全表匹配&#xff0c;得到对应的行 比如有个表&#xff1a; SELECT * FROM my_table按照sku_id分组后&#xff0c;选择record_date最大的那一行的全部值&#xff0c;先分组&#xff1a; SELECT sku_id,max(rec…

党建管理系统源码 搭建智慧党建小程序+支持在线缴费、考试、学习 功能强大

随着信息技术的飞速发展&#xff0c;党建工作也迎来了数字化、智能化的新时代。为了提升党建工作的效率&#xff0c;优化党员参与体验&#xff0c;基于党建管理系统源码的智慧党建小程序非常好用。分享一款春哥智慧党建小程序源码&#xff0c;该小程序集成了在线缴费、考试、学…

什么是蜜罐,在当前网络安全形势下,蜜罐能提供哪些帮助

在当前的互联网时代&#xff0c;网络安全威胁日益严峻&#xff0c;攻击手段层出不穷。为了应对这些威胁&#xff0c;网络安全专家们不断探索新的防御手段&#xff0c;在过去的几年里&#xff0c;一种更加积极主动的网络安全方法正在兴起。蜜罐技术便是这样一种备受瞩目的主动防…

echers配置项:折线图,折现的颜色修改

如上图所示&#xff1a;红框内的折现颜色修改&#xff0c;并隐藏默认的点 series: [{data: [1, 230, 224, 218, 135, 147, 760,1500,1200,2500,2000],type: line,lineStyle: {color: #00DBFE // 折现颜色},symbol:none, // 不显示点smooth: true, // 折现角度&#xff1a;圆滑…

ARM架构安全特性之防御执行技术

安全之安全(security)博客目录导读 目录 1、侧信道攻击威胁 2、推测屏障Speculation Barriers 3、栈溢出攻击威胁 4、指针认证PAC 5、分支目标识别BTI 6、内存安全违规威胁 7、内存标记扩展MTE 8、加强数据保护 9、特权不可访问&#xff08;Privileged Access Never …

Unity Mirror 从入门到入神(一)

Mirror从入门到成神 文章目录 Mirror从入门到成神简介NetworkClientRegisterPrefabConnect (string address)Disconnect ()activeactiveHost NetworkServerSpawn 简介 Mirror是一个unity网络同步框架&#xff0c;基于MonoBehaviour生命周期的回调的基础上进行数值的同步&#…

算法day08

第一题 1. 两数之和 由上述题意所知&#xff0c;本题要采用二分法的解题思路&#xff0c;二分法主要是面向有序的数组且也满足二段性的数组&#xff0c;所谓二段性就是在一定的规则下能把该数组分成两个部分&#xff1b; 本题注意要点&#xff1a; 1、循环结束的条件&#xff…

MMDetection内三个实用工具详解:日志分析、结果分析、混淆矩阵

实用工具目录 一、日志分析使用方法实际案例 二、结果分析pkl结果文件生成使用方法实际案例 三、混淆矩阵使用方法实际案例遇到的UserWarning解决方案 MMDetection官方除了训练和测试脚本&#xff0c;他们还在 mmdetection/tools/ 目录下提供了许多有用的工具。本帖先为大家重点…

Blender雕刻建模_笔画,镜像,动态拓扑

笔画 笔画选项&#xff0c;一般是对刷子&#xff08;自由线&#xff09;工具设置 描边方法如下&#xff1a;标红的为常用 -间隔&#xff1a;按一定间隔应用笔画的结果 例如&#xff1a;笔刷半径50&#xff0c;笔画间隔100%&#xff08;笔刷直径的百分比&#xff09;&#x…

聚苯并咪唑(PBI)为超高性能工程塑料 未来应用前景较好

聚苯并咪唑&#xff08;PBI&#xff09;为超高性能工程塑料 未来应用前景较好 聚苯并咪唑&#xff08;简称PBI&#xff09;&#xff0c;是一类以苯并咪唑基团作为结构重复单元的杂环聚合物。聚苯并咪唑不溶于水&#xff0c;溶于强极性溶剂&#xff0c;具有耐高温、耐腐蚀、抗辐…

Java小游戏之汤姆猫

背景&#xff1a; 博主写过羊了个羊小游戏&#xff0c;客户觉得羊了个羊同学写过了&#xff0c;想换一个&#xff0c;于是笔者想到了汤姆猫。就是那个以前在苹果手机上的猫。 过程&#xff1a; 初始会有一个猫的图片展示&#xff0c;然后你点击按钮&#xff0c;猫会有不同动作…

Python筑基之旅-溯源及发展

目录 一、Python的起源 二、Python的版本更替及变化 三、Python的优缺点 四、Python的发展方向 五、Python之禅 六、推荐专栏/主页&#xff1a; 1、Python函数之旅&#xff1a;Functions 2、Python算法之旅&#xff1a;Algorithms 3、个人主页&#xff1a;https://mye…

湖南大学OS-2018期末考试(不含解析)

前言 不知道哪里翻出来的一张&#xff0c;看着确实像期末考卷&#xff0c;暂且放一下。或许做过&#xff0c;或许没做过。 总之答案不记得了。做完可以评论区发一下或者找我发出来。 共6道大题。 一、(30%) 1. &#xff08;6%&#xff09; 进程间通信的两种方法分别是什么&…

Media Encoder 2024 for Mac:专业的音视频编码神器

Media Encoder 2024 for Mac&#xff0c;作为Mac用户的专业音视频编码工具&#xff0c;凭借其强大的功能和用户友好的界面&#xff0c;深受专业人士的喜爱。它支持将各种格式的音视频素材转换为多种流行格式&#xff0c;如MP4、MOV、AVI等&#xff0c;满足不同的播放和发布需求…

python:functools.partial和functools.wraps使用

python&#xff1a;functools.partial和functools.wraps使用 1 前言 python内置的functools模块&#xff0c;提供了一些非常好用的类或者方法&#xff0c;其中functools.partial和functools.wraps的使用频率较高&#xff0c;本文将针对其分析使用。 2 使用 2.1 functools.p…