当前位置: 首页 > news >正文

React项目react-pdf使用

react项目中展示pdf

1.安装依赖

npm install react-pdf

2.封装一个根据url展示pdf的组件

import { useState } from 'react'
import { Card } from "antd";
import style from './index.module.css'
import {message ,} from 'antd'
import PropTypes from 'prop-types';
import { Document, Page, pdfjs } from 'react-pdf'
import { DownOutlined, UpOutlined, MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import 'react-pdf/dist/esm/Page/AnnotationLayer.css'
import 'react-pdf/dist/esm/Page/TextLayer.css';
// 配置 PDF.js 的 worker 文件
pdfjs.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.js', import.meta.url).toString()
export default function PdfViewModal(props) {
    const [pageNumber, setPageNumber] = useState(1);
    const [numPages, setNumPages] = useState(1);
    const [scale, setScale] = useState(1.0);
    const onDocumentLoadSuccess = ({ numPages }) => {
        setNumPages(numPages)
    }
    //上一页
    const lastPage = () =>{
        if (pageNumber == 1) {
            message.info('已是第一页');
            return;
        }
        const page = pageNumber - 1;
        setPageNumber(page);
    }
    //下一页
    const nextPage = () =>{
        if (pageNumber == numPages) {
            message.info("已是最后一页");
            return;
        }
        const page = pageNumber + 1;
        setPageNumber(page);
    }
    //缩小
    const pageZoomOut = () => {
        if (scale <= 0.5) {
            message.info('已缩放至最小');
            return;
        }
        const newScale = scale - 0.1;
        setScale(newScale);
    }

    //放大
    const pageZoomIn = () => {
        if (scale >= 1) {
            message.info('已放大至最大');
            return;
        }
        const newScale = scale + 0.1;
        setScale(newScale);
    }

    return (
        <>
            <div className={style.setting_box}>
                <div className={style.setting_box_item} onClick={lastPage}><UpOutlined /></div>
                <div className={style.setting_box_item}>{pageNumber}/{numPages}</div>
                <div className={style.setting_box_item} onClick={nextPage}><DownOutlined /></div>
                <div className={style.setting_box_item} onClick={pageZoomIn}><PlusCircleOutlined /></div>
                <div className={style.setting_box_item} onClick={pageZoomOut}><MinusCircleOutlined /></div>
            </div>

            <Card className={style.pdf_box}>
            <Document 
                    file={new URL(props.url, import.meta.url).toString()}
                    onLoadSuccess={onDocumentLoadSuccess}
                >
                    <Page pageNumber={pageNumber} scale={scale} />
                </Document>
            </Card>
{/*             <div >

            </div> */}
        </>
    )
}

// 定义 propTypes 验证
PdfViewModal.propTypes = {
    url: PropTypes.string.isRequired,
};

// 设置默认 props
/* PdfViewModal.defaultProps = {
    url: '',
}; */

css样式

.setting_box {
    display: flex;
    justify-content: space-between;
    height: 16px;
    align-items: center;
    background-color: #444;
    opacity: 0.5;
    border-radius: 20px;
    padding: 3px 8px;
    width: 125px;
    margin: 0 auto;
}

.setting_box_item {
    color: #ffffff;
}

.pdf_box {
    display: flex;
    justify-content: center;
    height: calc(100vh - 125px);
    margin-top: 10px;
    overflow-y: scroll;
}

3.调用组件

  const items = [
    {
      key: '1',
      label: '课程内容',
      children: (
        <>
          {courseContent.pdfUrl && <PdfViewModal url={courseContent.pdfUrl}  />}
        </>
      ),
      icon: <FilePdfFilled />,
    },
    {
      key: '2',
      label: '课程视频',
      children: (
        <>
          {courseContent.videoUrl && <VideoViewModal url={courseContent.videoUrl} ref={voideChildRef} />}
        </>
      ),
      icon: <VideoCameraFilled />,
    },
    {
      key: '3',
      label: '知识图谱',
      children: (
        <>
          <ChartViewModal />
        </>
      ),
      icon: <InteractionFilled />,
    },
  ];

实现效果

相关文章:

  • P10452 货仓选址
  • 【devops】Github Actions Secrets | 如何在Github中设置CI的Secret供CI的yaml使用
  • LabVIEW 中 dotnet.llb 库功能
  • 图形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan简介
  • .net6 mvc 获取网站(服务器端)的IP地址和端口号
  • CTex安装和使用(1)
  • Windows 下安装 Python 和 Nodejs
  • 联想笔记本电脑摄像头灯亮,但没有画面怎么解决,
  • SM2加签、验签,加密、解密
  • 【洛谷】B3849 [GESP样题 三级] 进制转换
  • DeepSeek与ChatGPT的全面对比
  • electron 学习
  • 【virtiofs】ubuntu24.04+qemu7.0调试virtiofs
  • 洗牌加速!车规MCU“冷热交加”
  • rust学习一、入门之搭建简单开发环境
  • 【人工智能】通过python练习机器学习中的8大算法
  • SpringMVC详解
  • 使用爬虫获取1688商品分类:实战案例指南
  • 【技术解析】MultiPatchFormer:多尺度时间序列预测的全新突破
  • 固高控制卡的几种运动模式
  • “一节课、两小时”,体育正在回归“C位”
  • 墨西哥宣布就“墨西哥湾”更名一事起诉谷歌
  • 中国一重集团有限公司副总经理陆文俊被查
  • 融创中国:今年前4个月销售额约112亿元
  • 如此城市|上海老邬:《爱情神话》就是我生活的一部分
  • 黄玮接替周继红出任国家体育总局游泳运动管理中心主任