前端-选中pdf中的文字并使用,显示一个悬浮的翻译按钮(本地pdfjs+iframe)不适用textlayer
使用pdfjs移步–
vue2使用pdfjs-dist实现pdf预览(iframe形式,不修改pdfjs原来的ui和控件,dom层可以用display去掉一部分组件)
方案1:获取选择文本内容的最前面的字符坐标的位置(这种写法会导致如果选择超出pdf容器的高度之后,导致按钮显示不出来,这种方法显示位置固定)
方案2:获取选择文本最后鼠标离开位置的坐标(目前没发现bug,这种方法显示的位置不固定)这个方法在最下面,核心位置计算方法handleTextSelectionPdf,updateToolPositionPdf
- 实现案例
- pdf容器创建,悬浮盒子创建
<iframe:src="pdfurl"class="pdfContent"ref="pdfViewer"frameborder="0"width="100%"height="850px"></iframe><divv-show="selectionToolsVisible"class="selection-tools":style="selectionPosition"@mousedown.prevent><div class="tool-item" @click.stop="getAihelper('entocn')"><img src="../../assets/detailImage/enToCn.png" alt="" /><span class="tool-text">翻译</span></div></div>
- data实例
data() {return {selectionToolsVisible: false,selectionPosition: { top: '0px', left: '0px' },selectionTimer: null,};},
- mounted注册鼠标事件-注册pdf的监听
this.$refs.pdfViewer.onload = () => {const iframeDoc =this.$refs.pdfViewer.contentDocument ||this.$refs.pdfViewer.contentWindow.document;iframeDoc.addEventListener('mouseup', this.handleTextSelectionPdf);};
- pdf监听代码-方案1
handleTextSelectionPdf(e) {clearTimeout(this.selectionTimer);// 缓存关键事件属性const targetElement = e?.target || document.activeElement;// const cachedSelection = window.getSelection().toString().trim();this.selectionTimer = setTimeout(() => {const selection =this.$refs.pdfViewer.contentWindow.getSelection();// 增强型六重验证const isValid =selection.rangeCount > 0 &&!selection.isCollapsed &&selection.toString().trim().length >= 1 && // 允许单字符选择targetElement.closest('#viewerContainer');if (isValid) {// console.log(selection);const range = selection.getRangeAt(0);const rect = this.getAdjustedRectPdf(range);this.updateToolPositionPdf(rect);this.selectionToolsVisible = true;this.tempSelection = selection.toString();} else {this.selectionToolsVisible = false;}}, 50); // 优化响应时间},getAdjustedRectPdf(range) {const tempSpan = document.createElement('span');range.insertNode(tempSpan);const rect = tempSpan.getBoundingClientRect();tempSpan.remove();// 获取 iframe 在整个页面中的位置const iframeRect = this.$refs.pdfViewer.getBoundingClientRect();// **修正点:确保 top 计算正确**const absoluteTop = rect.top + iframeRect.top;const absoluteLeft = rect.left + iframeRect.left + window.scrollX;// console.log(`iframeRect:`, iframeRect);// console.log(`selection rect:`, rect);// console.log(// `absoluteTop: ${absoluteTop}, absoluteLeft: ${absoluteLeft}`// );return {top: absoluteTop,left: absoluteLeft,width: rect.width,height: rect.height,};},updateToolPositionPdf(rect) {const viewportWidth = window.innerWidth;const tooltipWidth = '';this.selectionPosition = {top: `${rect.top - 70}px`,left: `${Math.min(Math.max(rect.left, 10),viewportWidth - tooltipWidth - 10)}px`,maxWidth: `${tooltipWidth}px`,};// console.log(`Final tooltip position:`, this.selectionPosition);},
- 部分样式-按钮样式
<style scoped lang="less">
::v-deep .selection-tools {position: fixed;background: rgba(29, 115, 232, 1);border-radius: 5px;box-shadow: 0 4px 12px rgba(25, 118, 210, 0.15);padding: 8px;display: inline-flex;align-items: center;// gap: 6px;z-index: 9999;// opacity: 0;transform: translateY(-10px) scale(0.95);transition: all 0.1s cubic-bezier(0.4, 0, 0.2, 1);/* 移除默认的pointer-events限制 */pointer-events: auto !important;/* 修正激活状态逻辑 */&::after {content: '';position: absolute;bottom: -11px;left: 50%;transform: translateX(-50%);border: 6px solid transparent;border-top-color: #1d73e8;filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));}&.active {opacity: 1;transform: translateY(0) scale(1);}.tool-item {padding: 6px 12px;border-radius: 4px;cursor: pointer;display: flex;align-items: center;transition: all 0.2s;flex-direction: column;height: 50px;justify-content: space-between;// &:hover {// background: #f0f6ff;// transform: translateY(-1px);// .iconfont {// color: #0065cc;// }// .tool-text {// color: #003d82;// }// }.tool-text {font-family: Microsoft YaHei;font-weight: 400;font-size: 12px;color: #ffffff;// line-height: 41px;}}.tool-divider {width: 1px;height: 38px;background: #3f86dd;margin: 0 4px;}img {max-width: 24px;}
}
</style>
以上方法可能导致的问题就是如果选择内容超出了pdf框,会导致按钮显示不出来,所以改为选择之后的鼠标最后出现的位置上面,修改代码handleTextSelectionPdf,updateToolPositionPdf
pdf位置计算核心方法-方案2
handleTextSelectionPdf(e) {clearTimeout(this.selectionTimer);// 捕获鼠标坐标(相对视口)const mouseX = e.clientX;const mouseY = e.clientY;this.selectionTimer = setTimeout(() => {// 获取 PDF iframe 的文档对象const pdfWindow = this.$refs.pdfViewer.contentWindow;const pdfDocument = pdfWindow.document;// 计算 PDF 容器在页面中的位置const iframeRect = this.$refs.pdfViewer.getBoundingClientRect();// console.log(mouseX, 'mouseX');// console.log(mouseY, 'mouseY');// console.log(iframeRect.left, 'iframeRect.left');// console.log(iframeRect.top, 'iframeRect.top');// console.log(pdfWindow.scrollX, 'pdfWindow.scrollX');// console.log(pdfWindow.scrollY, 'pdfWindow.scrollY');// console.log(window.scrollX, 'window.scrollX');// console.log(window.scrollY, 'window.scrollY');// 转换坐标到 PDF 文档坐标系const pdfX = mouseX;const pdfY = mouseY;// 在 PDF 文档中检测元素const targetElement = pdfDocument.elementFromPoint(pdfX, pdfY);const isValid = targetElement?.closest('#viewerContainer');// 其他验证逻辑保持不变const selection = pdfWindow.getSelection();const isTextValid =selection.rangeCount > 0 &&!selection.isCollapsed &&selection.toString().trim().length >= 1;if (isValid && isTextValid) {// 使用鼠标坐标定位工具框const viewportX = mouseX + iframeRect.left;const viewportY = mouseY + iframeRect.top;this.updateToolPositionPdf(viewportX, viewportY);this.selectionToolsVisible = true;this.tempSelection = selection.toString();} else {this.selectionToolsVisible = false;}}, 50);},updateToolPositionPdf(absoluteX, absoluteY) {const tooltipWidth = ''; // 根据实际工具框宽度调整// 边界检测逻辑let finalLeft = absoluteX - 35;let finalTop = absoluteY - 62.7 - 20; // 减去按钮元素高度 然后上移一点this.selectionPosition = {top: `${finalTop}px`,left: `${finalLeft}px`,maxWidth: `${tooltipWidth}px`,};console.log(this.selectionPosition);},
相关文章:
前端-选中pdf中的文字并使用,显示一个悬浮的翻译按钮(本地pdfjs+iframe)不适用textlayer
使用pdfjs移步– vue2使用pdfjs-dist实现pdf预览(iframe形式,不修改pdfjs原来的ui和控件,dom层可以用display去掉一部分组件) 方案1:获取选择文本内容的最前面的字符坐标的位置(这种写法会导致如果选择超出…...
Mongodb分片模式部署
MongoDB 分片集群部署教程 1. 概述 MongoDB 分片是一种用于处理大规模数据集的集群技术。通过分片,MongoDB 可以将数据分布在多个服务器上,从而提高存储容量和读写性能。本教程将详细介绍如何从零开始部署 MongoDB 分片集群。 介绍 分片集群中主要由三…...
「一起学后端」Nest.js + MySQL 查询方法教学文档
Nest.js MySQL 查询方法教学文档 文章目录 Nest.js MySQL 查询方法教学文档1. 基础 CRUD 操作1.1 创建记录1.2 查询记录1.3 更新记录1.4 删除记录 2. 复杂查询2.1 分页与排序2.2 关联查询(JOIN)2.3 聚合查询2.4 子查询 3. 高级操作3.1 事务处理3.2 Typ…...
基于Spring Boot的企业内管信息化系统的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
【学习笔记】LLM推理与部署
文章目录 1 [LLMs inference] quantization 量化整体介绍(bitsandbytes、GPTQ、GGUF、AWQ)2 [LLMs inference] quantization 量化整体介绍(bitsandbytes、GPTQ、GGUF、AWQ)3 [LLMs serving] openrouter & vllm host LLM 推理服…...
leetcode-134.加油站
油箱容积无限,要求能环岛,说明总共加起来的油是不少于消耗量的,这是唯一一个决定能否环岛的变量,只要油量够,那么必定有一段路是攒油的路,它供给后续的消耗,使得油箱总是不空。 如果油量足够&am…...
companion object和object 从kotlin转java分析
说明 companion object 中 companion类中的方法是普通的方法 在外部类中生成静态变量,静态companion 对象 object MyClass2 中 类中方法是普通方法 在MyClass2中生成静态变量,静态MyClass2对象, 一 companion object 使用 kotlin转java pa…...
检索增强生成(2)本地PDF 本地嵌入模型
from langchain_community.document_loaders import PyPDFLoader from pathlib import Pathdef load_local_pdf(file_path):if not Path(file_path).exists():raise FileNotFoundError(f"文件 {file_path} 不存在!")loader PyPDFLoader(file_path)try:do…...
关于TVS管漏电流的问题?
问题描述: 在量产的带电池故事机生产中,工厂产线测试电流时,有1台机器电流比正常机器大10mA左右。 原因分析: 1、分析电路原理图,去除可能出现问题的电压或器件(不影响系统),发现…...
2025前端面试题记录
vue项目目录的执行顺序是怎么样的? 1、package.json 在执行npm run dev时,会在当前目录寻找package.json文件,此文件包含了项目的名称版本、项目依赖等相关信息。 2、webpack.config.js(会被vue-cli脚手架隐藏) 3、vue.config.js 对…...
Linux系统docker部署Ollama本地大模型及部署Hugging Face开源模型,ollama相关注意点,非ollama模型创建,模型量化,显存建议
本文主要描述在Linux系统使用docker部署ollama自有模型以及Hugging Face开源模型,也涉及到一些相关注意点,欢迎沟通讨论~ 拉取镜像 拉取ollama最新镜像:docker pull ollama/ollama:latest 运行ollama 执行:docker run -d --res…...
.NET 9 彻底改变了 API 文档:从 Swashbuckle(Swagger) 到 Scalar
示例代码下载:https://download.csdn.net/download/hefeng_aspnet/90404652 摘要 API 文档是现代软件开发的支柱。随着 .NET 9 从 Swashbuckle 转向 Microsoft.AspNetCore.OpenApi,开发人员需要新的策略来保持高效。本文探讨了这些变化,并介…...
C++——权限初识
权限初识 C中的访问权限主要分为三种: public 、 private 和 protected 。这些权限决定了类成员(包括数据成员和成员函数)的可访问性。以下是一个总结表格,说明了在不同情况下这些权限如何应用: 使用权限(…...
如何让自动驾驶汽车“看清”世界?坐标映射与数据融合概述
在自动驾驶领域,多传感器融合技术是实现车辆环境感知和决策控制的关键。其中,坐标系映射和对应是多传感器融合的重要环节,它涉及到不同传感器数据在统一坐标系下的转换和匹配,以实现对车辆周围环境的准确感知。本文将介绍多传感器融合中坐标系映射和对应的数学基础和实际应…...
如何在 Linux 系统中部署 FTP 服务器:从基础配置到安全优化
一、为什么选择 Linux 部署 FTP 服务器? FTP(文件传输协议)作为互联网最早的文件传输标准,至今仍在企业内部文件共享、镜像站点同步等场景中广泛应用。Linux 系统凭借其稳定性、开源特性及丰富的工具链,成为搭建 FTP 服…...
C++——引用
目录 举个例子: 引用的基本特性 引用的定义语法如下: 1. 引用必须初始化: 2. 引用是别名: 3. 引用不能为空: 4. 引用不能重新绑定: 引用的使用场景 函数参数传递: 函数返回值…...
unity开发效率提升笔记
本文将记录提升Unity开发效率的若干细节,持续更新 一.VSCode文件标签多行显示 1.File->Preference->Settings (快捷键Ctrl 逗号) 2.搜索workbench.editor.wrapTabs 3.勾选上这个单选开关 若依然不是多行 4.搜索workbench.editor.tabSizing,选择fi…...
VScode页面错误,可以编译C++20版本,但页面显示有错误的解决方案
问题回顾 学习信号量时使用到了C20版本的一些变量,可以正常编译和运行,但在编辑器上显示存在错误,如图所示 显示结果,提示命名空间std没有成员变量counting_semaphore,如图所示 解决办法 1、确保自己安装了C/C插件…...
[WEB开发] JDBC
一. JDBC基础 JDBC (Java DataBase Connectivity): 就是使用 java 语言操作数据库的一套API. JDBC本质: 一套标准接口, 规范各个数据库厂商实现这套接口, 提供驱动使用接口, 真正执行的是实现类 二. 实战 2.1 非预编译sql // 1. 注册数据库驱动Class.forName("com.my…...
Linux shell脚本2-test条件测试语句:文件类型、字符串是否相等、数字大小比较、多重条件判断,测试语句验证
目录 1.条件测试语句 2.文件表达式测试 2.1测试文件状态的条件表达式 2.2程序验证 2.2.1 单个文件验证 2.2.3.两个文件验证 3.字符串表达式测试 4.数字表达式测试 5.复合表达式测试 1.条件测试语句 在写shell脚本时,经常遇到的问题就是判断字符串是否相等&…...
linux_git使用
1. git的历史 git是开源的 2. git的理解 版本控制 只进行管理源文件 3. git的使用 3.1. git命令安装 sudo yum install git sudo apt install -y git 查看是否安装成功 $git --version 3.2. git使用注意事项 首次使用git需要输入用户名和邮件 gitignore࿱…...
Linux网络相关概念和重要知识(2)(UDP套接字编程、聊天室的实现、观察者模式)
目录 1.UDP套接字编程 (1)socket编程 (2)UDP的使用 ①socket ②bind ③recvfrom ④sendto 2.聊天室的实现 (1)整体逻辑 (2)对sockaddr_in的封装 (3)…...
2025年03月18日柯莱特(外包宁德)一面前端面试
目录 自我介绍你怎么从0到1搭建项目的webpack 的构建流程手写webpack插件你有什么想问我的吗 2. 你怎么从 0 到 1 搭建项目的 在面试中回答从 0 到 1 搭建前端项目,可按以下详细步骤阐述: 1. 项目前期准备 需求理解与分析 和产品经理、客户等相关人…...
汇川EASY系列之以太网通讯(MODBUS_TCP做主站)
汇川Easy系列以太网通讯中(MODBUSTCP,plc做主站),终于可以不用使用指令就可以完成了,全程通过简单的配置就可通讯。本文将通过EASY系列PLC与调试助手之间完成此操作。具体演示如下; 关于主站和从站的介绍 A/请求:即主动方 向被动方发送的一个要求的信息。 B/主站:发…...
uni-app jyf-parser将字符串转化为html 和 rich-text
uni-app jyf-parser将字符串转化为html-CSDN博客 方法二: rich-text | uni-app...
PyTorch中Batch Normalization1d的实现与手动验证
PyTorch中Batch Normalization1d的实现与手动验证 一、介绍 Batch Normalization(批归一化)是深度学习中常用的技术,用于加速训练并减少对初始化的敏感性。本文将通过PyTorch内置函数和手动实现两种方式,展示如何对三维输入张量…...
LoRA中黑塞矩阵、Fisher信息矩阵是什么
LoRA中黑塞矩阵、Fisher信息矩阵是什么 1. 三者的核心概念 黑塞矩阵(Hessian) 二阶导数矩阵,用于优化问题中判断函数的凸性(如牛顿法),或计算参数更新方向(如拟牛顿法)。 Fisher信息矩阵(Fisher Information Matrix, FIM) 统计学中衡量参数估计的不确定性,反映数据…...
Transformer中,Fisher矩阵与权重之间关系
Transformer中,Fisher矩阵与权重之间关系 目录 Transformer中,Fisher矩阵与权重之间关系一、Fisher矩阵与Transformer权重的关系二、Fisher矩阵的更新方式三、举例说明给出案例:Transformer权重矩阵,Fisher矩阵,说明对应关系和怎么更新二阶导数计算需要大量算力有什么方法…...
本地安装deepseek大模型,并使用 python 调用
首先进入 ollama 官网 https://ollama.com/点击下载 下载完成后所有都是下一步,就可以 点击搜索 Models : https://ollama.com/search然后点击下载: 选择后复制: ollama run deepseek-r1:32b例如: 让它安装完成后࿱…...
asp.net mvc 向前端响应json数据。用到jquery
最近在给客户开发提醒软件时,用asp.net mvc 开发。该框架已经集成了bootstrap,直接贴asp.net mvc 端代码: {Layout null; }<!DOCTYPE html><html> <head><meta name"viewport" content"widthdevice-width" /…...
《基于深度学习的指纹识别智能门禁系统》开题报告
个人主页:大数据蟒行探索者 1研究背景 1.1开发目的和意义 指纹识别作为生物特征识别领域的一项重要技术,在安全认证、犯罪侦查和个人身份验证等方面具有广泛应用前景。随着深度学习技术的迅猛发展,基于深度学习的指纹识别系统成为了当前研究…...
数据预处理流程与关键步骤解析
数据预处理流程图(Markdown格式): #mermaid-svg-b3mhJcpFWaJ9qMZ8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-b3mhJcpFWaJ9qMZ8 .error-icon{fill:#552222;}#mermaid-svg-b3m…...
单片机开发资源分析实战——以STM32F103ZET6为例子,分析我们的单片机
目录 第一件事情:为什么叫STM32F103ZET6 分析我们的资源手册 第二件事情,关心我们的GPIO引脚输出 第三件事情:去找对应外设的说明部分 本文章隶属于项目: Charliechen114514/BetterATK: This is a repo that helps rewrite ST…...
uv命令介绍(高性能Python包管理工具,旨在替代pip、pip-tools和virtualenv等传统工具)
文章目录 **主要功能**1. **快速安装和管理 Python 包**2. **生成和管理锁文件 (requirements.lock)**3. **创建虚拟环境**4. **与 poetry 兼容** **核心优势**1. **极快的速度**:基于 Rust 实现,利用多线程和缓存大幅加速依赖解析。2. **轻量且独立**&a…...
React Native进阶(六十):webview实现屏蔽所嵌套web页面异常弹窗
文章目录 一、前言二、解决方案三、注意事项四、拓展阅读 一、前言 在React Native项目集成web页面时,webview嵌套方式是常用方式。如果所嵌套的web页面由于某种不可控因素导致出现错误弹窗信息,webview作为web嵌套方式应该对其行为可控。 React Nativ…...
IS-IS原理与配置
一、IS-IS概述 IS-IS(Intermediate System to Intermediate System,中间系统到中间系统)是ISO(International Organization for Standardization,国际标准化组织)为它的CLNP(ConnectionLessNet…...
响应式CMS架构优化SEO与用户体验
内容概要 在数字化内容生态中,响应式CMS架构已成为平衡搜索引擎可见性与终端用户体验的核心载体。该系统通过多终端适配技术,确保PC、移动端及平板等设备的内容渲染一致性,直接降低页面跳出率并延长用户停留时长。与此同时,智能S…...
mysql 主从配置
核心概念: 主服务器(Master):负责处理客户端的写操作,并将数据更改记录到二进制日志(binlog)中。从服务器(Slave):负责读取主服务器的二进制日志,…...
Windows下编译安装Qt5.15.0指南
1. 系统要求 操作系统: Windows 7 或更高版本(推荐 Windows 10/11)。 磁盘空间: 至少 20-30 GB(编译过程会生成大量中间文件)。 内存: 建议 8GB 或更高。 编译器: 需要安装 Visual Studio(推荐 MSVC 2017 或 MSVC 2…...
001-JMeter的安装与配置
1.前期准备 下载好JMeter : https://jmeter.apache.org/download_jmeter.cgi 下载好JDK : :Java Downloads | Oracle 中国 下载图中圈蓝的JMeter和JDK就行,让它边下载,我们边往下看 2.为什么要下载并安装JDK ? JMeter 是基于 Java 开发的工具&#…...
kube-score K8S Yaml静态代码分析工具详解
kube-score 是一款专注于 Kubernetes 配置文件的静态代码分析工具,旨在通过自动化检查帮助用户识别资源配置中的潜在问题,并遵循最佳实践以提升集群的安全性、稳定性和性能。以下是其核心功能、使用方法和应用场景的详细解析: 一、核心功能与…...
【Go】Go语言结构体笔记
整体介绍 虽然 Go 语言不是传统意义上的面向对象语言,但它提供了结构体(struct)来组织数据,并且可以为结构体绑定方法,从而达到面向对象的部分效果。 关键知识点包括: 结构体定义与实例化 定义结构体时使用…...
Oracle数据库性能优化全攻略:十大关键方向深度解析与实践指南
文章目录 一、SQL查询优化二、索引优化三、内存管理四、I/O优化五、分区表与分区索引六、并行处理七、统计信息管理八、锁与并发控制九、数据库参数调优十、应用设计优化结论 在当今数据驱动的时代,数据库的性能优化成为了确保企业应用高效运行的关键。Oracle作为业…...
Modern C++面试题及参考答案
目录 解释右值引用的定义及其与左值引用的核心区别 std::move 的实现原理是什么?为什么它本身不执行移动操作? 移动构造函数与拷贝构造函数的调用场景有何不同? 实现一个支持移动语义的类需要遵循哪些原则? 完美转发(Perfect Forwarding)的实现原理及 std::forward 的…...
【单片机通信技术应用——学习笔记三】液晶屏显示技术,取模软件的应用
一、液晶显示技术简介 1.RGB信号线 RGB是一种色彩模式,是工业界的一种颜色标准,是通过红(R)、绿(G)、蓝(B)三个颜色通道的变化,以及它们相互之间的叠加来得到各式各样的…...
Git push后撤销提交
一、介绍 当某次更改完工程后,push了本地仓库到云端,但是发现有地方改错了,想撤销这次推送,或者某次提交就更改了很小一部分,想和本地这次修改的合并为一次推送,省的在云端显示特别多次提交,显得…...
React多层级对象改变值--immer
reduxjs/toolkit底层就是immer,,,所以在使用redux的时候,直接赋值,就会响应式的数据 如果不使用reduxjs/toolkit,可以自己使用immer来实现 安装immer npm install immer引入produce函数,,prod…...
17153. 班级活动(蓝桥杯-python)
代码写法 import os import sys# 请在此输入您的代码n int(input()) a list(map(int,input().split()))da {} flag1 0 flag2 0for i in a:da[i] da.get(i,0)1for i,j in da.items():if j 1:flag1 1if j > 2:flag2 j-2if flag2 > flag1:print(flag2) else:print(…...
html5-qrcode前端打开摄像头扫描二维码功能
实现的效果如图所示,全屏打开并且扫描到二维码后弹窗提醒,主要就是使用html5-qrcode这个依赖库,html5-qrcode开源地址:GitHub - mebjas/html5-qrcode: A cross platform HTML5 QR code reader. See end to end implementation at:…...
【后端】【Django】【ORM】SearchFilter 详解
SearchFilter 详解 SearchFilter 是 Django REST Framework(DRF)提供的一个过滤器,用于在 ModelViewSet 视图集中支持搜索功能。它允许用户通过 URL 查询参数(默认 search)对多个字段进行模糊匹配。 一、基本用法 &a…...