react-pdf實(shí)現(xiàn)pdf文件上下翻頁(yè)放大縮小等功能的預(yù)覽

項(xiàng)目為react工程,引入ant design組件庫(kù),導(dǎo)入react-pdf組件庫(kù)。

Talk is cheap, show me the code.

  • 創(chuàng)建一個(gè)pdfPreview.js類(lèi)以及樣式文件pdfPreview.less文件

pdfPreview.js

import React, { Component } from 'react';
import { Spin, Tooltip,Input } from 'antd';
import Icon, { LeftOutlined, RightOutlined, PlusCircleOutlined, MinusCircleOutlined, FullscreenOutlined, FullscreenExitOutlined } from '@ant-design/icons';
import styles from './pdfPreview.less';

import { Document, Page, pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

class pdfPreview extends Component {

  constructor(props) {
    super(props);
    this.state = {
      pageNumber: 1,
      pageNumberInput: 1,
      pageNumberFocus: false,
      numPages: 1,
      pageWidth: 200,
      fullscreen: false
    };
  }

  onDocumentLoadSuccess = ({ numPages }) => {
    this.setState({ numPages: numPages })
  }

  lastPage = () => {
    if (this.state.pageNumber == 1) {
      return
    }
    const page = this.state.pageNumber - 1
    this.setState({ pageNumber: page ,pageNumberInput:page})
  }
  nextPage = () => {
    if (this.state.pageNumber == this.state.numPages) {
      return
    }
    const page = this.state.pageNumber + 1
    this.setState({ pageNumber: page ,pageNumberInput:page})
  }
  onPageNumberFocus = e => {
    this.setState({ pageNumberFocus: true })
  };
  onPageNumberBlur = e => {
    this.setState({ pageNumberFocus: false ,pageNumberInput:this.state.pageNumber})
  };
  onPageNumberChange = e => {
    let value=e.target.value
    value=value<=0?1:value;
    value=value>=this.state.numPages?this.state.numPages:value;
    this.setState({ pageNumberInput: value })
  };
  toPage = e => {
    this.setState({ pageNumber: Number(e.target.value) })
  };

  pageZoomOut = () => {
    if (this.state.pageWidth <= 200) {
      return
    }
    const pageWidth = this.state.pageWidth * 0.8
    this.setState({ pageWidth: pageWidth })
  }
  pageZoomIn = () => {
    const pageWidth = this.state.pageWidth * 1.2
    this.setState({ pageWidth: pageWidth })
  }

  pageFullscreen = () => {
    if (this.state.fullscreen) {
      this.setState({ fullscreen: false, pageWidth: 200 })
    } else {
      this.setState({ fullscreen: true, pageWidth: 400 - 40 })
    }
  }

  render() {
    const { pageNumber, pageNumberFocus, pageNumberInput,numPages, pageWidth, fullscreen } = this.state;
    debugger;
    return (
      <div className={styles.view}>
        <div className={styles.pageContainer}>
          <Document
            file={this.props.file}
            onLoadSuccess={this.onDocumentLoadSuccess}
            loading={<Spin size="large" />}
          >
            <Page pageNumber={pageNumber} width={pageWidth} loading={<Spin size="large" />} />
          </Document>
        </div>

        <div className={styles.pageTool}>
          <Tooltip title={pageNumber == 1 ? "已是第一頁(yè)" : "上一頁(yè)"}>
            <LeftOutlined onClick={this.lastPage} />
          </Tooltip>
          <Input value={pageNumberFocus ? pageNumberInput : pageNumber}
            onFocus={this.onPageNumberFocus}
            onBlur={this.onPageNumberBlur}
            onChange={this.onPageNumberChange}
            onPressEnter={this.toPage} type="number" /> / {numPages}
          <Tooltip title={pageNumber == numPages ? "已是最后一頁(yè)" : "下一頁(yè)"}>
            <RightOutlined onClick={this.nextPage} />
          </Tooltip>
          <Tooltip title="放大">
            <PlusCircleOutlined onClick={this.pageZoomIn} />
          </Tooltip>
          <Tooltip title="縮小">
            <MinusCircleOutlined onClick={this.pageZoomOut} />
          </Tooltip>
          <Tooltip title={fullscreen ? "恢復(fù)默認(rèn)" : '適合窗口'}>
            {fullscreen ? <FullscreenExitOutlined onClick={this.pageFullscreen} /> : <FullscreenOutlined onClick={this.pageFullscreen} />}
          </Tooltip>
        </div>
      </div>
    );
  }
}

export default pdfPreview;

pdfPreview.less

.view {
  background:#444;
  display: flex;
  justify-content: center;
  // height: 100vh;
  max-height: 600px;
  padding: 50px 0;
  overflow: auto;
}
.pageContainer {
  box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 4px 0px;
  width:max-content;
  max-width:100%;
}
.pageTool{
  position: absolute;
  bottom: 26px;
  background: rgb(66, 66, 66);
  color: white;
  padding: 8px 15px;
  border-radius: 15px;
  span{
    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;
  }
}

  • 組件使用
import PdfPreview from '../../components/pdfPreview';

  // 傳入pdf文件
  <PdfPreview file={xxx} />
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容