使用pdf.js封装react移动端 pdf 预览组件,可以手势缩放

1.安装需要的依赖

"pdfjs-dist": "^2.2.228"
"alloyfinger": "^0.1.7", 
"css3transform": "^1.2.3"

安装命令

npm i pdfjs-dist
npm i [email protected]
npm install css3transform

2.封装React pdf 预览组件

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import PDFJS from 'pdfjs-dist';
import styles from './index.scss';
import {isPdfFile} from './../../utils/utils';
import AlloyFinger from 'alloyfinger';
import Transform from 'css3transform';

PDFJS.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDFJS.version}/pdf.worker.js`;

export class PDF extends Component {
    constructor(props) {
        super(props)
        this.state = {
            pdf: null, // pdf 对象
            scale: 1.2, // 渲染规模
            isPdfFileTrue: true, // pdf 文件是否正确获取
            fileErrorText: '' // 错误提示语
        }
    }

    getChildContext() {
        const {pdf, scale} = this.state;
        return {
            pdf,
            scale
        }
    }

    componentDidMount() {
        const {src} = this.props;
        // 不是pdf文件不能继续渲染
        if (!isPdfFile(src)) {
            this.setState({
                isPdfFileTrue: false,
                fileErrorText: '无效或损坏的 PDF 文件'
            })
            return;
        }

        //获取pdf文件流
        let loadingTask = PDFJS.getDocument(src);
        let _this = this;
        loadingTask.promise.then(function (pdf) {
            if (pdf) {
                _this.setState({
                    pdf
                })
            } else {
                _this.setState({
                    isPdfFileTrue: false
                })
            }
        }, function (exception) {
            let message = exception && exception.message;
            console.log('message--' + message);
            let loadingErrorMessage = '';

            if (exception instanceof PDFJS.InvalidPDFException) {
                loadingErrorMessage = '无效或损坏的 PDF 文件';
            } else if (exception instanceof PDFJS.MissingPDFException) {
                loadingErrorMessage = '缺少 PDF 文件';
            } else if (exception instanceof PDFJS.UnexpectedResponseException) {
                loadingErrorMessage = '意外的服务器响应错误';
            } else {
                // pdf文件跨域请后端设置跨域https://blog.csdn.net/weixin_40660221/article/details/84138924
                loadingErrorMessage = '载入 PDF 时发生错误, 原因可能是文件跨域';
            }
            _this.setState({
                isPdfFileTrue: false,
                fileErrorText: loadingErrorMessage
            })
        })
    }

    render() {
        const {isPdfFileTrue, fileErrorText} = this.state;
        const {children} = this.props;
        return (
            
{isPdfFileTrue ? children : fileErrorText}
) } } PDF.childContextTypes = { pdf: PropTypes.object, scale: PropTypes.number } export class Page extends Component { constructor(props) { super(props) this.state = { status: 'N/A',// 加载pdf的状态 'N/A':初始状态 'loading':加载中 'rendering':渲染中 'rendered':渲染完成 page: null, // pdf页面 width: 0, // pdf页面宽度 height: 0, // pdf页面高度 } } componentDidMount() { this._update(this.context.pdf); } _update(pdf) { if (pdf) { this._loadPage(pdf); } else { this.setState({ status: 'loading' }) } } _loadPage(pdf) { const {status, page} = this.state; if (status === 'rendering' || page !== null) { return; } const {index} = this.props; pdf.getPage(index).then(this._renderPage.bind(this)) this.setState({ status: 'rendering' }) } _renderPage(page) { let {scale} = this.context; let viewport = page.getViewport(scale); let {width, height} = viewport; let canvas = this.refs.canvas; let context = canvas.getContext('2d'); // 高清显示pdf canvas.width = width * 2; canvas.height = height * 2; canvas.style.width = width + 'px'; canvas.style.height = height + 'px'; canvas.style.overflow = 'scroll'; context.scale(2, 2); page.render({ canvasContext: context, viewport }) this.setState({ status: 'rendered', page, width, height }) } render() { let {width, height, status} = this.state; console.log('status--' + status); return (
) } } Page.contextTypes = PDF.childContextTypes export class Viewer extends Component { // 手势放大缩小 pdf handlePinch = () => { let pdfViewer = this.refs.pdfViewer; Transform(pdfViewer); let initScale = 1; let pdfViewerAf = new AlloyFinger(pdfViewer, { pinch: (evt) => { console.log('pinch'); } }); pdfViewerAf.on('pinch', (evt) => { const {zoom} = evt; let zoomTemp = 0; // 限制缩放比例为 0.42~1.5 if (zoom < 0.42) { zoomTemp = 0.42; } else if (zoom > 1.5) { zoomTemp = 1.5; } else { zoomTemp = zoom; } pdfViewer.scaleX = pdfViewer.scaleY = initScale * zoomTemp; }); } componentDidMount() { this.handlePinch(); // 手势放大缩小 pdf } render() { let {pdf = {}} = this.context; let numPages = pdf ? pdf.numPages : 0; let fingerprint = pdf ? pdf.fingerprint : 'none'; let pages = Array.apply(null, {length: numPages}) .map((v, i) => ()) return (
{pages}
) } } Viewer.contextTypes = PDF.childContextTypes;
// index.scss
.pdfContext {  
  float: left;  
  width: 100%;  
  height: 100%;  
}  
  
.pdfPage {  
  float: left;  
  width: 100%;  
  height: 100%;  
}  
  
.pdfViewer {  
  float: left;  
  width: 100%;  
  height: 100%;  
}
// utils/utils.js
export function isPdfFile(pdf) {
    if (!pdf) {
        return false;
    }
    if (!/\.(pdf)$/.test(pdf.toLowerCase())) {
        return false;
    } else {
        return true;
    }
}

3.页面调用方式

import {PDF, Viewer} from '../../components/pdfViewer';


return (  
    
);
.pdfWrap {  
  position: relative;  
  width: 100%;  
  height: 100%;  
  top: 0;  
  bottom: 0;  
  left: 0;  
  right: 0;  
  text-align: center;  
  background: #F8F8F8;  
  line-height: 0.6rem;  
  font-size: 0.32rem;  
  overflow: scroll;  
}

你可能感兴趣的:(pdf,react.js,手势,前端,移动端web)