react-pdf实现pdf文件上下翻页放大缩小等功能的预览

项目为react工程,引入ant design组件库,导入react-pdf组件库。

Talk is cheap, show me the code.

  • 创建一个pdfPreview.js类以及样式文件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 ? "已是第一页" : "上一页"}>
            <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 ? "已是最后一页" : "下一页"}>
            <RightOutlined onClick={this.nextPage} />
          </Tooltip>
          <Tooltip title="放大">
            <PlusCircleOutlined onClick={this.pageZoomIn} />
          </Tooltip>
          <Tooltip title="缩小">
            <MinusCircleOutlined onClick={this.pageZoomOut} />
          </Tooltip>
          <Tooltip title={fullscreen ? "恢复默认" : '适合窗口'}>
            {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} />
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容