pdf预览组件react-pdf,pdfjs-dist

news/2024/7/27 14:51:35/文章来源:https://blog.csdn.net/q553866469/article/details/137329693

   "react": "^17.0.2" 

1.react去预览pdf文件,并且这个组件可以在移动端展示,但要注意安装版本

 "react-pdf": "^5.7.2"

直接上代码了,做了一个两页的分页,因为放在移动端有个问题,有个文件全部加载手机就卡死了,但这个分页也没解决问题,换了个文件就是好的,代码能优化的地方比较多,自行优化:

import React, { useState, useEffect, useCallback } from 'react';
import { Page, pdfjs } from "react-pdf";
import { Document } from 'react-pdf/dist/esm/entry.webpack';pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;const PdfViewer = ({ file }: any) => {const [page_jsx, set_page_jsx]: [any[], React.Dispatch<React.SetStateAction<any[]>>] = useState<any[]>([]);const [totalPages, setTotalPages]: [number, React.Dispatch<React.SetStateAction<number>>] = useState(0);const [end_num, set_end_num]: [any, React.Dispatch<React.SetStateAction<any>>] = useState(2);const viewMore = useCallback(() => {let current_end_num = end_num + 2 <= totalPages ? end_num + 2: totalPages;set_end_num(current_end_num);const array = [];for (let i = current_end_num - 2; i < current_end_num; i++) {array.push(i);}let pageJsx = array?.map((a: any) => <Page key={`page_${a}`} pageNumber={a + 1}/>);set_page_jsx((jsx_arr: any[]) => [...jsx_arr, ...pageJsx]);}, [end_num, totalPages, set_end_num, set_page_jsx])useEffect(() => {end_num === 2 && set_page_jsx([<Page key={`page_${0}`} pageNumber={1}/>,<Page key={`page_${1}`} pageNumber={2}/>]);}, [end_num, set_page_jsx])console.log('page_jsx:', page_jsx);return (<div><DocumentclassName={"pdf-content"}file={file}onLoadSuccess={({ numPages }: any) => setTotalPages(numPages)}>{page_jsx?.map((page: any) => page)}{totalPages > end_num && <div onClick={() => viewMore()}>View more</div>}</Document></div>);
};export default PdfViewer;

2.   pdfjs-dist

"pdfjs-dist": "^2.5.207",这个插件的版本尤其要记录下,网上查了好多,只把代码放上去,如果版本不对,引入文件路径是不存在的,那么还是直接放代码吧,如第一种方法自行优化下:

import React, { useCallback, useEffect, useRef, useState } from 'react';
const pdfjsLib = require('pdfjs-dist/es5/build/pdf.js');pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`;const PdfViewer = ({ file }: any) => {const [totalPages, setTotalPages]: [number, React.Dispatch<React.SetStateAction<number>>] = useState(0);const [end_num, set_end_num]: [any, React.Dispatch<React.SetStateAction<any>>] = useState(2);const canvasRefs: any = useRef([]);const pageNums: any = useRef([]);const getPage = useCallback(async (pdf: any, endNum: any) => {pageNums.current = new Array(endNum)?.fill(0).map((_, i) => i + 1);console.log('end_num:', endNum);// 渲染每一页for (let i = endNum - 1; i <= endNum; i++) {const page = await pdf.getPage(i);const viewport = page.getViewport({ scale: 1.5 });// 创建canvas元素const canvas = document.createElement('canvas');const context = canvas.getContext('2d');canvas.height = viewport.height;canvas.width = viewport.width;// 将canvas添加到DOM中const canvasContainer: any = document.getElementById('pdf-container');canvasContainer.appendChild(canvas);// 存储canvas的引用以便后续操作canvasRefs.current[i - 1] = canvas;// 渲染页面const renderContext = {canvasContext: context,viewport: viewport};await page.render(renderContext);}}, [])useEffect(() => {async function loadPdf() {const loadingTask = pdfjsLib.getDocument(file);const pdf: any = await loadingTask.promise;// 获取总页数const numPages: any = pdf.numPages;setTotalPages(numPages);getPage(pdf, end_num);}if (file) {loadPdf();}}, [file, end_num, getPage])return (<><div id="pdf-container">{/* 在这里,canvas元素将被动态添加到这个容器中 */}</div>{totalPages !== end_num && <div onClick={async () => {if (end_num < totalPages) {let current_end_num = end_num + 2 <= totalPages ? end_num + 2: totalPages;set_end_num(current_end_num);const loadingTask = pdfjsLib.getDocument(file);const pdf: any = await loadingTask.promise;getPage(pdf, current_end_num);}}} style={{height: '40px', lineHeight: '40px', textAlign: 'center'}}>View more</div>}</>);
};export default PdfViewer;

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

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

相关文章

51单片机学习笔记14 LCD1602显示屏使用

51单片机学习笔记14 LCD1602显示屏使用 一、LCD1602介绍1. 简介2. 引脚定义3. DDRAM4. 字模5. 指令&#xff08;1&#xff09;清屏指令 0x01&#xff08;2&#xff09;光标归位指令 0x02&#xff08;3&#xff09;进入模式设置指令 0x06&#xff08;4&#xff09;显示开关控制指…

JavaScript中什么叫深拷贝?

在 JavaScript 中&#xff0c;深拷贝指的是创建一个新的对象&#xff0c;这个新的对象与原始对象完全独立&#xff0c;没有任何共享的属性或者数据&#xff0c;它们不共享同一块内存地址。深拷贝会复制原始对象的所有属性和嵌套对象的所有属性&#xff0c;包括嵌套对象中的属性…

Ts递归查找多个根节点树结构某一条数据

// 递归查找树结构数据 function getIsNode(nodes: any, code: string) {let found false;function search(nodes: any) {nodes.forEach((node: any) > {if (node.code code) { //code相等&#xff0c;视为找到&#xff0c;将found设置为truefound true;}// 否则查找子节…

数据结构进阶篇 之【选择排序】详细讲解(选择排序,堆排序)

民以食为天&#xff0c;我以乐为先 嘴上来的嘘寒问暖&#xff0c;不如直接打笔巨款 一、选择排序 1.直接选择排序 SelectSort 1.1 基本思想 1.2 实现原理 1.3 代码实现 1.4 直接选择排序的特性总结 2.堆排序 HeapSort 跳转链接&#xff1a;数据结构 之 堆的应用 二、完…

OpenHarmony实战开发-如何通过Stage模型实现一个简单的游戏卡片

介绍 本示例展示了如何通过Stage模型实现一个简单的游戏卡片。 通过卡片支持的点击事件进行交互&#xff0c;让用户通过点击的先后顺序把一个乱序的成语排列成正确的成语。使用了C和TS的混合编程方式&#xff0c;将获取随机数的能力下沉到C实现&#xff0c;并通过NAPI的能力将…

牛客NC153 信封嵌套问题【中等 动态规划,最长递增子序列 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/9bf77b5b018d4d24951c9a7edb40408f 相同的题目&#xff1a; https://www.lintcode.com/problem/602 思路 本质是求最长子序列问题envelopes 先按 w 升序排序&#xff0c;再按 h 降序 排序&#xff0c;只需考虑h…

基于深度学习的机场航拍小目标检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要&#xff1a;在本博客中介绍了基于YOLOv8/v7/v6/v5的机场航拍小目标检测系统。该系统的核心技术是采用YOLOv8&#xff0c;并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;从而进行性能指标的综合对比。我们详细介绍了国内外在机场航拍小目标检测领域的研究现状、数据集处理…

Nginx三大常用功能“反向代理,负载均衡,动静分离”

注意&#xff1a;以下案例在Windows系统计算机作为宿主机&#xff0c;Linux CentOS 作为虚拟机的环境中实现 一&#xff0c;Nginx配置实例-反向代理 1.反向代理 案例一 实现效果&#xff1a;使用nginx反向代理&#xff0c;访问 www.123.com 直接跳转到127.0.0.1:8080 准备工…

vue3源码解析——ref和reactive定义响应式的区别

ref 和 reactive 是 Vue 3.0 中用于定义响应式数据的两个新 API。它们有以下区别&#xff1a; ref 定义单个响应式数据 数据类型可以是任意类型。它通常用于定义原始数据类型为响应式数据。返回一个响应式对象&#xff0c;该对象包含一个 .value 属性&#xff0c;可用于获取和设…

Golang Gin框架

1、这篇文章我们简要讨论一些Gin框架 主要是给大家一个基本概念 1、Gin主要是分为路由和中间件部分。 Gin底层使用的是net/http的逻辑&#xff0c;net/http主要是说&#xff0c;当来一个网络请求时&#xff0c;go func开启另一个协程去处理后续(类似epoll)。 然后主协程持续…

网络安全 | 什么是DDoS攻击?

关注WX&#xff1a;CodingTechWork DDoS-介绍 DoS&#xff1a;Denial of Service&#xff0c;拒绝服务。DDoS是通过大规模的网络流量使得正常流量不能访问受害者目标&#xff0c;是一种压垮性的网络攻击&#xff0c;而不是一种入侵手段。NTP网络时间协议&#xff0c;设备需要…

DSP实时计算平台设计方案:912-基于6U CPCIe的双路光纤图像DSP实时计算平台

基于6U CPCIe的双路光纤图像DSP实时计算平台 一、设备概述 设备基于6U CPCIe架构&#xff0c;通过背板交换实现4片信号处理板卡的互联传输&#xff0c;每个信号处理板卡支持双TMS320C6678&#xff0c;支持2路光纤的图像处理&#xff0c;实现FPGA的预处理和备份工…

Java基础知识总结(第八篇):集合:Collection(List、Set)、Map、Collections 工具类

声明: 1. 本文根据韩顺平老师教学视频自行整理&#xff0c;以便记忆 2. 若有错误不当之处, 请指出 系列文章目录 Java基础知识总结&#xff08;第一篇&#xff09;&#xff1a;基础语法 Java基础知识总结&#xff08;第二篇&#xff09;&#x…

159 Linux C++ 通讯架构实战14,epoll 函数代码实战

ngx_epoll_init函数的调用 //&#xff08;3.2&#xff09;ngx_epoll_init函数的调用&#xff08;要在子进程中执行&#xff09; //四章&#xff0c;四节 project1.cpp&#xff1a;nginx中创建worker子进程&#xff1b; //nginx中创建worker子进程 //官方nginx ,一个…

HarmonyOS 应用开发之页面和自定义组件生命周期

在开始之前&#xff0c;我们先明确自定义组件和页面的关系&#xff1a; 自定义组件&#xff1a;Component装饰的UI单元&#xff0c;可以组合多个系统组件实现UI的复用&#xff0c;可以调用组件的生命周期。 页面&#xff1a;即应用的UI页面。可以由一个或者多个自定义组件组成…

Topaz Video AI for Mac v5.0.0激活版 视频画质增强软件

Topaz Video AI for Mac是一款功能强大的视频处理软件&#xff0c;专为Mac用户设计&#xff0c;旨在通过人工智能技术为视频编辑和增强提供卓越的功能。这款软件利用先进的算法和深度学习技术&#xff0c;能够自动识别和分析视频中的各个元素&#xff0c;并进行智能修复和增强&…

区块链web3智能合约开发学习-开发工具Remix(1)

学习区块链中常用语言solidity时&#xff0c;我们会用到特别的开发工具&#xff0c;对于学习前期&#xff0c;建议是将代码写到Remix IDE中进行编译部署和测试&#xff0c;这就是我们编写和交互智能合约的地方&#xff0c; 在线remix编译器&#xff1a; https://remix.ethereu…

腾讯云(CVM)托管进行权限维持

前言 刚好看到一个师傅分享了一个阿里云ECS实战攻防&#xff0c;然后想到了同样利用腾讯云CVM的托管亦可实现在实战攻防中的权限维持。 简介 腾讯云自动化助手&#xff08;TencentCloud Automation Tools&#xff0c;TAT&#xff09;是一个原生运维部署工具&#xff0c;它可…

单片机中的RAM vs ROM

其实&#xff0c;单片机就是个小计算机。大计算机少不了的数据存储系统&#xff0c;单片机一样有&#xff0c;而且往往和CPU集成在一起&#xff0c;显得更加小巧灵活。 直到90年代初&#xff0c;国内容易得到的单片机是8031&#xff1a;不带存储器的芯片&#xff0c;要想工作&a…

基于SpringBoot的“校园志愿者管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“校园志愿者管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 志愿者注册…