实现了pdf翻页,放大,缩小,全屏展示,右键打印。
实现代码:
js:
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Spin, Tooltip, Input } from 'antd';
import { LeftOutlined, RightOutlined, PlusCircleOutlined, MinusCircleOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons';
import styles from './index.less';
import { Document, Page, pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
import stateStorage from '@/storage/stateStorage';
export default function PdfView({ file }) {
console.log(file)
const [pageNumber, setPageNumber] = useState(1)
const [pageNumberInput, setPageNumberInput] = useState(1)
const [pageNumberFocus, setPageNumberFocus] = useState(false)
const [numPages, setNumPages] = useState(1)
const [pageWidth, setPageWidth] = useState(600)
const [fullscreen, setFullscreen] = useState(false)
const onDocumentLoadSuccess = ({ numPages }) => {
setNumPages(numPages)
}
const lastPage = () => {
if (pageNumber == 1) {
return
}
const page = pageNumber - 1
setPageNumber(page)
setPageNumberInput(page)
}
const nextPage = () => {
if (pageNumber == numPages) {
return
}
const page = pageNumber + 1
setPageNumber(page)
setPageNumberInput(page)
}
const onPageNumberFocus = e => {
setPageNumberFocus(true)
};
const onPageNumberBlur = e => {
setPageNumberFocus(false)
setPageNumberInput(pageNumber)
};
const onPageNumberChange = e => {
let value = e.target.value
value = value <= 0 ? 1 : value;
value = value >= numPages ? numPages : value;
setPageNumberInput(value)
};
const toPage = e => {
setPageNumber(Number(e.target.value))
};
const pageZoomOut = () => {
if (pageWidth <= 600) {
return
}
const pageWidths = pageWidth * 0.8
setPageWidth(pageWidths)
}
const pageZoomIn = () => {
const pageWidths = pageWidth * 2.5
setPageWidth(pageWidths)
}
const pageFullscreen = () => {
if (fullscreen) {
setFullscreen(false)
setPageWidth(600)
} else {
setFullscreen(true)
setPageWidth(window.screen.width - 40)
}
}
const getPrintRender = () => {
return new Array(numPages || []).fill(0).map((ele, i) => {
return (
<Page key={i + 1} pageNumber={i + 1} width={750} loading={<Spin size="large" />} />
)
})
}
return (
<div className={styles.view}>
<div className={`${styles.pageContainer} ${styles.noPrint}`}>
<Document
file={stateStorage.get('pdf')}
onl oadSuccess={onDocumentLoadSuccess}
loading={<Spin size="large" />}
>
<Page pageNumber={pageNumber} width={pageWidth} loading={<Spin size="large" />} />
</Document>
</div>
<div className={styles.canPrint}>
<Document
file={stateStorage.get('pdf')}
onl oadSuccess={onDocumentLoadSuccess}
loading={<Spin size="large" />}
>
{getPrintRender()}
</Document>
</div>
<div className={`${styles.pageTool} ${styles.noPrint}`}>
<Tooltip title={pageNumber == 1 ? '已是第一页' : '上一页'}>
<LeftOutlined onClick={lastPage} />
</Tooltip>
<Input value={pageNumberFocus ? pageNumberInput : pageNumber}
onFocus={onPageNumberFocus}
onBlur={onPageNumberBlur}
onChange={onPageNumberChange}
onPressEnter={toPage} type="number" /> / {numPages}
<Tooltip title={pageNumber == numPages ? '已是最后一页' : '下一页'}>
<RightOutlined onClick={nextPage} />
</Tooltip>
<Tooltip title="放大">
<PlusCircleOutlined onClick={pageZoomIn} />
</Tooltip>
<Tooltip title="缩小">
<MinusCircleOutlined onClick={pageZoomOut} />
</Tooltip>
<Tooltip title={fullscreen ? '恢复默认' : '适合窗口'}>
{fullscreen ? <FullscreenExitOutlined onClick={pageFullscreen} /> : <FullscreenOutlined onClick={pageFullscreen} />}
</Tooltip>
</div>
</div>
)
}
PdfView.propTypes = {
params: PropTypes.object.isRequired,
file: PropTypes.any
};
css:
.view {
background: #444;
display: flex;
justify-content: center;
min-height: 100vh;
padding: 50px 0;
box-sizing: border-box;
}
.pageContainer {
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 4px 0px;
width: max-content;
max-width: 100vw;
}
.pageTool {
position: fixed;
bottom: 20px;
background: rgb(66, 66, 66);
color: white;
padding: 8px 15px;
border-radius: 15px;
i {
padding: 5px;
margin: 0 5px;
&:hover {
background: #333;
}
}
input {
display: inline-block;
width: 50px;
text-align: center;
margin-right: 10px;
height: 24px;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"] {
-moz-appearance: textfield;
}
}
.view {
.canPrint {
display: none;
}
@media print {
.canPrint {
display: block;
}
& {
padding: 0;
}
&::-webkit-scrollbar {
display: none;
}
.noPrint {
display: none;
height: 0;
}
:global {
// react-pdf__Page__textContent隐藏 为了解决打印时会出现多一张空白页的情况
.react-pdf__Page__textContent {
display: none;
}
.react-pdf__Page:not(:last-child) {
page-break-after: always;
}
}
}
}
附:
react-pdf