关于pdf.js中文本坐标尺寸的使用

news2024/9/20 14:58:29

        一个电子教材项目中有这样一个需求:

       用户向网站上传一个PDF书籍后,网站可以对PDF书籍进行解析,并支持用户对PDF书籍的每一页做一些操作,比如:为英语课本的单词和句子添加音频热区。因为热区数量很多,所以,希望网站 “在初始化课本页面的时候,自动初始化热区,然后用户再在此基础上调整”,这样可以大大减少工作量。

        我使用pdf.js来实现该功能,该库可以获取到pdf中的文本及位置、宽高,但这些位置尺寸使用起来有几处值得注意的细节(稍不注意,可能会被卡很久)。

一、pdf.js提供的文本信息

        如图所示,这是一个PDF页面中获取到的文本信息。这里要用到的字段有:height(高)、width(宽)、transform(这是组matrix矩阵数据,其中最末两位分别是水平方向和垂直方向的位置信息)。

二、transform数据对应的坐标系

        1)初始坐标数据

        通常,我们定位一个元素时,会设置它的left和top,left的数值从左向右递增,top的数值自上而下递增;而transform中的垂直方向数值是从下往上递增的。(下图是坐标系不同导致的错误结果,这个结果是多种原因造成的,后续我们逐一修正)

        2)矫正坐标数据(垂直方向翻转)

        基于上一步,首先,先来矫正坐标系。我们将垂直方向的数值进行矫正:

新值 = pdf页面高度 - 旧值。

        再次渲染后,会发现垂直方向的坐标系已经对了。但仍有两个问题:一个是横纵方向的定位都存在偏差,另一个是热区的宽高比实际文本所占空间大。这主要是因为“绘制pdf的canvas画布的width、height”和“canvas画布在页面布局中被定义的样式style中的width、height”不一致,二者存在比例换算。

三、数据换算

        1)矫正比例换算

        基于上一步,结合canvas的内外尺寸来矫正热区的宽高和定位:

left = textinfo.transform[4] / canvas.width * canvas.style.width;

top = textinfo.transform[5] / canvas.height * canvas.style.height;

width = textinfo.width / canvas.width * canvas.style.width;

height = textinfo.height / canvas.height * canvas.style.height;

        再次渲染后,会发现水平方向的尺寸、定位已经对了。但垂直方向上的定位仍然存在少许偏差。这个问题很细节,我困扰了好几个小时才发觉:我们已经知道初始时的垂直坐标是自下而上的,那么在垂直翻转时,应该把文本所占的高度也减掉才对。

        2)再次矫正垂直方向数值

新值 = (pdf页面高度 - 旧值 - 文本自身高度) / canvas.height * canvas.style.height。

        修改后再次渲染,可以发现效果已经符合预期了。

四、相关代码片段展示

initHotspots() {
    let pdfDoc = this.loadingTaskDict[this.pageActiveIndex] || this.loadingTask;
    if (!pdfDoc) return;
    pdfDoc.promise.then((pdf) => {
        let pageIndex = this.loadingTaskDict[this.pageActiveIndex] ? 1 : this.pageActiveIndex;
        pdf.getPage(pageIndex).then((page) => {
            let view = page.view || [];
            let pdfPageWidth = view[2] - view[0]; // pdf页面宽度(canvas.width)
            let pdfPageHeight = view[3] - view[1]; // pdf页面高度(canvas.height)
            page.getTextContent().then((textInfo) => {
                textInfo = textInfo || {};
                let textItems = textInfo.items || [];
                // bookPageDom是网页中pdf页面的包裹元素(bookPageInfo.width相当于canvas.style.width)
                let bookPageDom = document.querySelector('.book-page');
                let bookPageInfo = bookPageDom ? bookPageDom.getBoundingClientRect() : null;
                textItems.forEach((v) => {
                    if (/[a-zA-Z]+/i.test(v.str) && v.str.length > 7 && bookPageInfo) {
                        let x = (v.transform[4] / pdfPageWidth) * 100 + '%';
                        let y = ((pdfPageHeight - (v.transform[5] + v.height)) / pdfPageHeight) * 100 + '%';
                        this.addHotpot({
                            top: y,
                            'y%': y,
                            left: x,
                            'x%': x,
                            width: (v.width / pdfPageWidth) * bookPageInfo.width,
                            height: (v.height / pdfPageHeight) * bookPageInfo.height,
                            original: v.str,
                            styles: { left: x, top: y }
                        });
                    }
                });
            });
        });
    });
},

五、最后

        上方的截图,因为受制于页面布局,课本页面的尺寸比较小,看不清楚。所以,下面是一张demo效果图:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言进阶课程学习记录- 函数与宏分析

C语言进阶课程学习记录- 函数与宏分析 实验-宏和函数实验-宏的副作用实验-宏的妙用小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 实验-宏和函数 #include <stdio.h>#define RESET(p, len) …

详解Mixtral-8x7B背后的MoE!

高端的模型往往只需最朴素的发布方式。 这个来自欧洲的大模型团队在12月8日以一条磁力链接的方式发布了Mixtral-8x7B,这是一种具有开放权重的**「高质量稀疏专家混合模型」**(SMoE)。 该模型在大多数基准测试中都优于Llama2-70B,相比之下推理速度快了6倍,同时在大多数标准基…

Web3 游戏周报(4.14-4.20)

【4.14-20】Web3 游戏行业动态&#xff1a; 前迪士尼老板与漫威、星球大战人才携手推出 Web3 游戏工作室 加密集换式卡牌游戏《Fantasy》在 Blast 主网上线 加密游戏工作室 Avalon 融资 1,000 万美元&#xff0c;Hashed 领投 Faraway 收购 Yuga Labs 旗下两大游戏 IP“HV-MT…

JSON Web Token 入门

JSON Web Token&#xff08;缩写 JWT&#xff09;是目前最流行的跨域认证解决方案&#xff0c;本文介绍它的原理和用法。 一、跨域认证的问题 互联网服务离不开用户认证。一般流程是下面这样。 1、用户向服务器发送用户名和密码。 2、服务器验证通过后&#xff0c;在当前对话&…

以赛促学、生态共建 | 软通动力子公司鸿湖万联成功举办基于x86架构的OpenHarmony应用生态挑战赛

近日&#xff0c;由开放原子开源基金会、央视网、江苏省工业和信息化厅、无锡市人民政府、江苏软件产业人才发展基金会、苏州工业园区、无锡高新区等共同承办&#xff0c;鸿湖万联参与共建的“基于x86架构的OpenHarmony应用生态挑战赛”决赛路演在无锡圆满落幕。本次挑战赛历时…

贪心(贪婪)算法

主要思想 贪心算法的思想主要可以概括为“总是做出当前看起来最优的选择”&#xff0c;也就是不从整体上进行考虑&#xff0c;所得到的答案是某种意义上的局部最优解&#xff0c;不一定是整体最优解。 贪心算法没有固定算法框架&#xff0c;算法设计的关键是贪心策略的选择。…

统一SQL 支持Oracle CHAR和VARCHAR2 (size BYTE|CHAR)转换

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;Postgresql&#xff0c;TDSQL-MySQL&#xff0c;达梦8&#xff0c;LightDB-Oracle 操作目标 在Oracle中的CHAR和VARCHAR2数据类型&…

以始为终梳理前端的发展方向

嗨&#xff0c;我是小路。一位努力向上生长的90后前端开发工程师。 以下是正文&#xff1a; 前段时间朋友和我吐槽&#xff1a;“做了多年的PHP开发&#xff0c;突然被离职&#xff0c;然后去招聘市场一看&#xff0c;发现PHP已经没有市场了。偶尔会出现一两个相关的职位&#…

AI一键生成的解说短剧,如何导出工程文件到剪映二次编辑?

用鬼手剪辑可以一键生成解说视频 鬼手剪辑的一键生成解说视频是一种快速简便的AI解说工具&#xff0c;可以帮助用户将短视频转换为解说视频。该工具通过语音识别、自然语言处理和视频剪辑等技术&#xff0c;自动生成解说词并完成视频剪辑。 一键生成解说操作教程 一键生成解说…

PCB的层叠结构

有pcb的用处&#xff1a; 是为了防止线乱和占面积 PCB单层板&#xff1a;如果有人触电了&#xff0c;是算设计师没有设计好&#xff0c;还是操作员没有操作好&#xff0c;没有进行责任划分 防止触电&#xff0c;加绿皮 偶数版子&#xff1a;上下冲压对称性更好&#xff0c;不…

基于灰狼算法的综合能源系统多时间尺度优化调度(附matlab程序)

0.代码链接 基于灰狼算法的综合能源系统多时间尺度优化调度&#xff08;MATLAB程序&#xff09;资源-CSDN文库 1.简述 对于冷、热、电联供综合能源系统优化问题&#xff0c;为了提高可再生能源利用率&#xff0c;故以弃风、弃光量最小和综合能源系统运行经济性为优化目标&…

数据结构之顺序表的实现(C语言版)

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关顺序表的有关知识 所属专栏&#xff1a;数据结构 创作不易&#xff0c;望得到各位佬们的互三呦 一.前言 1.首先在讲顺序表之前我们先来了解什么是数据结构 数据结构是由“数据”和“结构”两词组合⽽来。 什…

个人音乐播放网站项目(SpringBoot+Linux部署上线)

在做完第一个博客系统项目以后&#xff0c;接着做下一个项目&#xff1a;音乐播放网站项目&#xff0c;此项目应用的技术栈和第一个项目是差不多的&#xff0c;即算是学完SSM等知识以后的两个入门级Java开发项目吧。 此项目包含的核心功能有&#xff1a; 一、登录、注册、退出…

【C++】:构造函数和析构函数

目录 前言一&#xff0c;构造函数**1.1 什么是构造函数****1.2 构造函数的特性**1.3 总结 二&#xff0c;析构函数**2.1 什么是析构函数****2.2 析构函数的特性****2.3 总结** 前言 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并…

Nginx 四层和七层代理

四层&#xff1a;通过报文中的目标地址和端口&#xff0c;加上负载均衡设备设置的服务器选择方式&#xff0c;决定最终选择的内部服务器&#xff0c;使用tcp、udp协议。 七层&#xff1a;"内容交换"&#xff0c;通过报文中真正有意义的应用层内容&#xff0c;加上负…

【MATLAB报错】错误使用 sym>tomupad Unable to convert ‘uss‘ to ‘sym‘.解决方法

出错代码如下&#xff1a; syms s; % Gnom matrix g11 13.8 / (0.16 * s 1); g12 -0.05 / (0.1 * s 1); g21 0.1 / (0.3 * s 1); g22 4.25 * s / (0.84 * s - 1); Gnom [g11 g12; g21 g22];w1 makeweight(0.2, 35, 9); w2 makeweight(0.25, 40, 8); W blkdiag(w1, …

vue+springboot实验个人信息,修改密码,忘记密码功能实现

前端部分 新增Person&#xff08;个人页面&#xff09;&#xff0c;Password&#xff08;修改密码页面&#xff09;&#xff0c;还需要对Manager&#xff0c;login页面进行修改 router文件夹下的index.js&#xff1a; import Vue from vue import VueRouter from vue-router i…

服务器基础知识(1)

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;服务器❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 1、什么是服务器 服务器是计算机的一种&#xff0c;它比普通计算机运行更快、负载更高、价格更贵。服务…

顺序表(快速上手数据结构)

在介绍ArrayList之前, 我们需要先了解List. List是一个接口,它继承于Collection接口(Collection又继承于最顶层的接口Iterable). 从数据结构的角度来看,List就是一个线性表(Linear List),即n个具有相同类型元素的有限序列, 在该序列上可以执行增删查改等操作. 注意: List是一…

GaN HEMT中短沟道效应的建模

来源&#xff1a;Modeling of Short-Channel Effects in GaN HEMTs&#xff08;TED 20年&#xff09; 摘要 在本文中&#xff0c;我们提出了一种用于估算GaN高电子迁移率晶体管&#xff08;HEMT&#xff09;器件中短沟道效应&#xff08;SCEs&#xff09;的显式和解析的基于电…