關(guān)于React項目中的PDF展示解決方案
本文將梳理兩種方案,涉及兩個庫react-pdf
和pdf.js
,使用環(huán)境為ant-design-pro腳手架創(chuàng)建的項目。
使用iframe標簽
1.不需要任何依賴的兩種方式為
直接使用iframe標簽展示pdf文件
<iframe src={fileUrl} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
其中fileUrl為需要展示pdf的文件地址,寬高和style均可自定義,下不贅述。
如果用戶可以訪問google,則可以使用如下地址:
<iframe src={`http://docs.google.com/gview?url=${fileUrl}&embedded=true`} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
其中fileUrl為需要展示pdf的文件地址,寬高和style均可自定義。
2.使用編譯好的靜態(tài)庫pdf.js的viewer.html展示
├── config # umi 配置,包含路由,構(gòu)建等配置 ├── mock # 本地模擬數(shù)據(jù) ├── public # 將編譯好的PDFJS放在這個目錄下 │ └── favicon.png # Favicon ├── src │ ├── assets # 本地靜態(tài)資源 │ ├── components # 業(yè)務(wù)通用組件 │ ├── e2e # 集成測試用例 │ ├── layouts # 通用布局 │ ├── models # 全局 dva model │ ├── pages # 業(yè)務(wù)頁面入口和常用模板 │ ├── services # 后臺接口服務(wù) │ ├── utils # 工具庫 │ ├── locales # 國際化資源 │ ├── global.less # 全局樣式 │ └── global.ts # 全局 JS ├── tests # 測試工具 ├── README.md └── package.json
如下圖所示:
在需要展示PDF文件的地方,使用如下src即可。
<iframe src={`pdfjs-2.2.228-dist/web/viewer.html?file=${fileUrl}`} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
使用react-pdf展示
import { Pagination } from 'antd'; import React, { useState } from 'react'; import { Document, Page } from 'react-pdf/dist/esm/entry.webpack'; // @ts-ignore const PdfViewer: React.FC<{ url: string }> = ({ url }) => { const [numPages, setNumPages] = useState(0); const [pageNumber, setPageNumber] = useState(1); // @ts-ignore const onDocumentLoadSuccess = (props: any) => { setNumPages(props?.numPages); }; const onChangePage = (page: any) => { setPageNumber(page); }; return ( <div> <div style={{ marginBottom: 4 }}> <a href={url} target={'_blank'} rel="noreferrer"> 查看當(dāng)前文件 </a> </div> <Document file={url} onLoadSuccess={onDocumentLoadSuccess}> <Page pageNumber={pageNumber} /> </Document> <Pagination style={{ marginTop: 4, display: 'flex', justifyContent: 'flex-end' }} total={numPages} simple hideOnSinglePage showTotal={(total) => `共 ${total} 頁`} current={pageNumber} pageSize={1} size="small" onChange={onChangePage} /> </div> ); }; export default PdfViewer;
pdfjs的另一種使用方式
import { useEffect, useRef, useState } from 'react'; const PDFJsViewer = ({ pdfUrl }: any) => { const pdfjsLib = require('pdfjs-dist/build/pdf.js'); const pdfjsWorker = require('pdfjs-dist/build/pdf.worker.entry.js'); pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker; const canvasRef = useRef(null); const [scale, setScale] = useState(1); const [offset, setOffset] = useState({ x: 0, y: 0 }); const handleWheel = (e: any) => { if (e.deltaY < 0) { setScale((prevScale) => Math.min(prevScale + 0.1, 3)); } else { setScale((prevScale) => Math.max(prevScale - 0.1, 0.5)); } }; const handleMouseDown = (e: any) => { const initialX = e.clientX - offset.x; const initialY = e.clientY - offset.y; const handleMouseMove = (e: any) => { const newX = e.clientX - initialX; const newY = e.clientY - initialY; setOffset({ x: newX, y: newY }); }; const handleMouseUp = () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; useEffect(() => { const canvas = canvasRef.current; //@ts-ignore const ctx = canvas.getContext('2d'); const loadingTask = pdfjsLib.getDocument(pdfUrl); loadingTask.promise.then((pdf: any) => { pdf.getPage(1).then((page: any) => { const viewport = page.getViewport({ scale: scale }); //@ts-ignore canvas.height = viewport.height; //@ts-ignore canvas.width = viewport.width; ctx.setTransform(1, 0, 0, 1, 0, 0); //@ts-ignore ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.setTransform(scale, 0, 0, scale, offset.x, offset.y); const renderContext = { canvasContext: ctx, viewport: viewport, }; page.render(renderContext); }); }); }, [pdfUrl, scale, offset]); return <canvas ref={canvasRef} onWheel={handleWheel} onMouseDown={handleMouseDown}></canvas>; }; export default PDFJsViewer;
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解webpack2+node+react+babel實現(xiàn)熱加載(hmr)
這篇文章主要介紹了詳解webpack2+node+react+babel實現(xiàn)熱加載(hmr) ,非常具有實用價值,需要的朋友可以參考下2017-08-08React?Hooks--useEffect代替常用生命周期函數(shù)方式
這篇文章主要介紹了React?Hooks--useEffect代替常用生命周期函數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09ForwardRef?useImperativeHandle方法demo
這篇文章主要為大家介紹了ForwardRef?useImperativeHandle方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03使用React-Router實現(xiàn)前端路由鑒權(quán)的示例代碼
這篇文章主要介紹了使用React-Router實現(xiàn)前端路由鑒權(quán)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07React Native時間轉(zhuǎn)換格式工具類分享
這篇文章主要為大家分享了React Native時間轉(zhuǎn)換格式工具類,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10