高亮img、pdf重点部分(html2canvas、pdfjs-dist、react-pdf)
可用业务场景
报销单据审批中,高亮发票部分
需求
后台返回一张图片或者pdf
、返回一组坐标
,坐标类型[number,number,number,number]
,分别代表了x、y、width、height。需要根据坐标在图片上高亮出来坐标位置。如下图
高亮的坐标是:
const rect: Rect[] = [[100, 100, 200, 200],[200, 300, 200, 200],
];
技术选型
- dom转成图片:html2canvas
- pdf预览:pdfjs-dist、react-pdf
- 遮照:纯css实现(四个绝对定位的dom)
这里的react-pdf使用的是V4,用来兼容IE11
遮照也可以换成是一个矩形框,看具体需求,我这里的需求是遮照高亮
代码
组件部分
/** @Author: Do not edit* @Date: 2023-08-25 13:48:06* @LastEditors: atwlee* @LastEditTime: 2023-08-28 14:08:34* @Descripttion:* @FilePath: /test/src/pages/generate.tsx*/import { FC, useEffect, useRef } from "react";
import styles from "./index.modules.less";
import html2canvas from "html2canvas";
import { Document, Page, pdfjs } from "react-pdf";pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.js",import.meta.url
).toString();export type Rect = [number, number, number, number];interface GenerateProps {fileUrl: string;rects: Rect[];onGenerateCallback: (imgs: string[]) => void;fileType: "img" | "pdf";fileSize?: [number, number];
}const Index: FC<GenerateProps> = (props) => {const { fileUrl, rects, onGenerateCallback, fileType, fileSize } = props;const divRef = useRef<HTMLDivElement>(null);const handleGenerateImg = () => {const results: string[] = [];rects.forEach((item, index) => {html2canvas(divRef.current!.querySelector(`[data-key="generate${index}"]`)!,{useCORS: true,}).then((canvas) => {results.push(canvas.toDataURL("image/png"));results.length === rects.length && onGenerateCallback(results);});});};const pdf2img = useRef<string[]>([]);const onPageLoadSuccess = () => {rects.forEach((item, index) => {html2canvas(divRef.current!.querySelector(`[data-key="generate${index}"]`)!,{useCORS: true,}).then((canvas) => {pdf2img.current.push(canvas.toDataURL("image/png"));if (pdf2img.current.length === rects.length) {onGenerateCallback(pdf2img.current);pdf2img.current = [];}});});};useEffect(() => {fileType === "img" && handleGenerateImg();}, [fileUrl, rects, fileType]);return (<div ref={divRef} className={styles.contanier}>{/* pdf */}{fileType === "pdf" && (<Document file={fileUrl}>{rects.map((i, index) => (<divclassName={styles.rectItem}key={index}data-key={`generate${index}`}><PagepageNumber={1}width={fileSize?.[0]}height={fileSize?.[1]}onRenderSuccess={onPageLoadSuccess}/><div className={styles.coverTop} style={{ height: i[1] }} /><divclassName={styles.coverRight}style={{left: i[0] + i[2],top: i[1],height: i[3],}}/><divclassName={styles.coverBottom}style={{ top: i[1] + i[3] }}/><divclassName={styles.coverLeft}style={{ width: i[0], top: i[1], height: i[3] }}/></div>))}</Document>)}{/* img */}{fileType === "img" &&rects.map((i, index) => (<divclassName={styles.rectItem}key={index}data-key={`generate${index}`}><img src={fileUrl} width={fileSize?.[0]} height={fileSize?.[1]} /><div className={styles.coverTop} style={{ height: i[1] }} /><divclassName={styles.coverRight}style={{left: i[0] + i[2],top: i[1],height: i[3],}}/><div className={styles.coverBottom} style={{ top: i[1] + i[3] }} /><divclassName={styles.coverLeft}style={{ width: i[0], top: i[1], height: i[3] }}/></div>))}</div>);
};export default Index;
使用
/** @Author: Do not edit* @Date: 2023-08-24 15:57:05* @LastEditors: atwlee* @LastEditTime: 2023-08-28 14:13:37* @Descripttion:* @FilePath: /test/src/pages/index.tsx*/
import { useState } from "react";
import Generate from "./generate";
import type { Rect } from "./generate";
import yayJpg from "./yay.jpg";
import pdfUrl from "./redv2.pdf";const rect: Rect[] = [[100, 100, 200, 200],[200, 300, 200, 200],
];export default function HomePage() {const [imgs, setImgs] = useState<string[]>([]);const onGenerateCallback = (img: string[]) => {setImgs(img);};const hiddenStyle = { height: 0, overflow: "hidden" };return (<div><h2>Yay! Welcome to umi!</h2><div style={hiddenStyle}><Generate// fileType="pdf"fileType="img"// fileUrl={pdfUrl}// fileUrl={'https://www.sdta.cn/pdf/e-map.pdf'}fileUrl={yayJpg}// fileUrl={// "https://img1.baidu.com/it/u=2488875768,1454762303&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800"// }rects={rect}onGenerateCallback={onGenerateCallback}/></div>{imgs.map((i, index) => {return <img src={i} key={index} alt="" />;})}</div>);
}
demo源码
PS
图片的话不用在意实际的宽度和高度,当然如果有更好。pdf不知道需不需要实际的宽度和高度,这里抛出去了fileSize的属性,demo里没有使用,没有测试。
相关文章:

高亮img、pdf重点部分(html2canvas、pdfjs-dist、react-pdf)
可用业务场景 报销单据审批中,高亮发票部分 需求 后台返回一张图片或者pdf、返回一组坐标,坐标类型[number,number,number,number],分别代表了x、y、width、height。需要根据坐标在图片上高亮出来坐标位置。如下图 高亮的坐标是࿱…...

18.神奇导航菜单指示器
效果 源码 <!DOCTYPE html> <html> <head> <title>Magic Menu Indicator | 03</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body><div class="navig…...

WPF+Prism+WebApi 学习总结
一、基本概念 WPF:WPF(Windows Presentation Foundation)是(微软推出的)基于Windows的用户界面框架,提供了统一的编程模型,语言和框架,做到了分离界面设计人员与开发人员的工作;WPF…...

uniapp热更新
首先热更新需要wgt包; 其次先了解这两个组件 下载的方法 安装的组件 场景: 当你项目的js文件或者页面文件或者静态图片文件css文件更新的时候可以走热更新; 而当你安装新的组件插件或者开启新的权限等功能的时候就无法通过热更新进行更新了…...

AUTOSAR从入门到精通-【应用篇】基于CAN协议的汽车尾气后处理诊断系统的软件开发(续)
目录 尾气后处理诊断程序的开发 5.1 数据库的解析 5.1.1 寻找XML文件 5.1.2 读取XML文件...

mybatis plus新版代码生成器,类型转换处理器ITypeConvertHandler使用
目录 引言关键代码源码分析记录一坑类型转换的第二种方式完整源码地址 引言 当默认生成的数据类型不满足时,就需要自定义指定要生成的类型 关键代码 FastAutoGenerator.create(url, username, password).dataSourceConfig(builder -> {builder.typeConvertHandl…...

python中的matplotlib画直方图(数据分析与可视化)
python中的matplotlib画直方图(数据分析与可视化) import numpy as np import pandas as pd import matplotlib.pyplot as pltpd.set_option("max_columns",None) plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus]Fa…...

【详解】文本检测OCR模型的评价指标
关于文本检测OCR模型的评价指标 前言:网上关于评价标准乱七八糟的,有关于单词的,有关于段落的,似乎没见过谁解释一下常见论文中常用的评价指标具体是怎么计算的,比如DBNet,比如RCNN,这似乎好像…...

Python遥感图像处理应用篇038 GDAL 遥感图像特征提取(统计特征图)
1.图像统计特征 遥感图像的统计特征是对图像中像素值的统计分布进行定量化描述的过程。这些统计特征可以提供关于图像内容和特性的有用信息。下面是一些常用的遥感图像统计特征描述方法: 平均值(Mean):计算图像中所有像素值的平均值,可以反映整个图像的亮度水平。 方差(…...

全局ID生成方式
全局ID生成方式 目录 1. 全局唯一id介绍 1.1 特点 2. 常见的全局唯一id生成策略 2.1 利用数据库自增字段生成id2.2 UUID2.3 Redis生成id2.4 zookeeper生成ID2.5 Twitter的snowflake算法 3. 面试题目:实现一个全局的ID生成器,注意线程安全 3.1 单例模式…...

c++之指针
总结性质 我们如何在一个函数中获取数组的长度: 我们都知道,在main函数中我们获得数组的长度只需要使用sizeof(a)/sizeof(a【0】)即可获得,但当我们把一个数组传入到方法时,c默认把…...

JVM 访问对象的两种方式
Java 程序会通过栈上的 reference 数据来操作堆上的具体对象。由于 reference 类型在《Java 虚拟机规范》里面只规定了它是一个指向对象的引用,并没有定义这个引用应该通过什么方式去定位、访问到堆中对象的具体位置,所以对象访问方式也是由虚拟机实现而…...

yo!这里是Linux基础开发工具介绍
目录 前言 基础开发工具 yum vim 1.基本介绍 2.基本操作 3.正常模式常用命令 4.底行模式常用命令 gcc/g gdb 1.基本介绍 2.常用操作 make/Makefile 1.背景 2.介绍 3.使用 git 1.介绍 2.操作 进度条程序简单实现 后记 前言 在学完初步的基础指令及权限控…...

本地组策略编辑器找不到怎么解决?| 解决windows home 版本隐藏本地组策略编辑器的问题 | 简单的介绍本地组策略编辑器
一般的 Windows 非家庭系统中,本地组策略编辑器不会被隐藏,但在某些特定情况下,可能会受到限制或不可用。如果你无法访问本地组策略编辑器,并且认为应该可以访问,请确保你拥有管理员权限,并检查是否有任何系…...

将Spring boot 项目部署到tomcat服务艰难
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z X Y Z...

第十二章 ObjectScript - 命令
文章目录 第十二章 ObjectScript - 命令命令熟悉的命令用于多维数组的命令 第十二章 ObjectScript - 命令 命令 本节概述了在 ObjectScript 常用命令。其中包括与其他语言中的命令相似的命令,以及其他语言中没有等效项的其他命令。 命令名称不区分大小写…...

在 CentOS 7 / RHEL 7 上安装 OpenSSL 1.1.x
OpenSSL 是一个开源软件库,由用于实现传输层安全 (TLS) 和安全套接字层 (SSL) 协议以及其他加密功能(例如签名、加密、解密和验证)的工具和库组成。操作系统和许多应用程序使用 OpenSSL 通过互联网提供安全通信。 CentOS 7 / RHEL 7 操作系统…...

论文阅读_模型结构_LoRA
name_en: LoRA: Low-Rank Adaptation of Large Language Models name_ch: LORA:大语言模型的低阶自适应 paper_addr: http://arxiv.org/abs/2106.09685 date_read: 2023-08-17 date_publish: 2021-10-16 tags: [‘深度学习’,‘大模型’] author: Edward J. Hu cita…...

uniapp获取 pdf文件流 并展示
1、流数据 uni.request({ url: this.$config.apiUrl“/api/report/content/fill?codebv.mf.refund.pay.voucher&busiNo00201323051500148949”, header: { ‘content-type’: ‘application/json;charsetutf-8’, ‘X-App-Code’: ‘weixin’, ‘X-Source’: ‘program’,…...

Linux(进程间通信)
目录 一、通信概念 二、进程间通信机制 1、管道 1.1 匿名管道(Anonymous Pipe) 1.2 命名管道(Named Pipe) 2、信号量 2.1 概念 2.2 API详解 2.3 使用示例 3、消息队列 3.1 概念 3.2 API函数 3.3 应用代码 4、共享内…...

Go的Gorm数据库操作错误WHERE conditions required
这是我在写这个代码处出现的问题 result : db.Save(&emergency) 这个错误是由于在提交保存数据时,GORM 需要指定 WHERE 条件,确保能够正确执行数据库操作。要解决这个问题,可以尝试使用 Create 方法替换 Save 方法,同时将创…...

基于java swing和mysql实现的仓库商品管理系统(源码+数据库+运行指导视频)
一、项目简介 本项目是一套基于java swing和mysql实现的仓库商品管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、项目文档、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经…...

6、css学习6(表格)
1、指定CSS表格边框,使用border属性。 2、表格双边框是因为th/td有各自独立的边框。 3、boder-collapse设置表格边框是否被折叠成一个单一的边框。 4、width和height属性定义表格的宽度和高度。 5、text-align属性设置水平对齐方式。 6、vertic-align属性设置垂…...

Ceph源码解析:PG peering
集群中的设备异常(异常OSD的添加删除操作),会导致PG的各个副本间出现数据的不一致现象,这时就需要进行数据的恢复,让所有的副本都达到一致的状态。 一、OSD的故障和处理办法: 1. OSD的故障种类: 故障A:一…...

解决jupyter notebook可以使用pytorch而Pycharm不能使用pytorch的问题
之前我是用的这个目录下的Python 开始更新目录 1、 2、 3、...

对建造者模式理解
当对象成员变量太多时,使用建造方法给变量赋值往往变得很臃肿,所以可以这样做 public class Something {private String a;private String b;private String c;private String d;private String e;public Something(Builder builder) {this.a builder.…...

回归预测 | MATLAB实现CSO-ELM布谷鸟算法优化极限学习机多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现CSO-ELM布谷鸟算法优化极限学习机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现CSO-ELM布谷鸟算法优化极限学习机多输入单输出回归预测(多指标,多图)效果一览基本介…...

静态链接库和动态链接库的区别
C静态链接库(Static Linking)和动态链接库(Dynamic Linking)的主要区别在于代码的组织和加载方式。 静态链接库 在编译时将库的代码和应用程序的代码合并在一起,生成一个单独的可执行文件。执行文件独立包含所需的库…...

使用 python 源码搭建 conda 环境
今天需要使用 python 2.6.8 的环境,发现 conda 设置成清华源后,没有旧版本了。所以打算从官网上下载一份 python 进行安装, 结果发现,conda 不能直接安装离线包(也可能我没找到方法),经过一番尝…...

dart 学习之 异步操作
import package:dio/dio.dart;// 定义一个异步函数,用于获取 URL 的内容 Future<String> getUrl(String url) async {Dio dio Dio();Response response await dio.get(url);return response.data; }void main() async {// 在主函数中执行异步操作var conten…...