There are a lot of plugins for DPF online preview, but most of them are not mature enough to be usable. I chose a Mozilla /pdf.js that I thought was relatively easy to use and suited our existing framework


Resources: Mozilla /pdf.js

The header brings in the Mozilla/pdF.js library

This library is not currently installed by NPM, directly imported in the header online or download a can be used

<! DOCTYPE html> <html lang="cn">
    <head>
        <meta charset="UTF-8">
        <meta content="yes" name="apple-mobile-web-app-capable">
        <meta content="yes" name="apple-touch-fullscreen">
        <meta content="telephone=no,email=no" name="format-detection">
        <title><%= htmlWebpackPlugin.options.title %></title>
        <link rel="stylesheet" href="./iconfont/iconfont.css">
        <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
        <script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
    </head>
    <body>
        <div id="appContainer"></div>
    </body>
</html>
Copy the code

Wrap a PDF component and just copy and paste this code

Class PDF extends React.Com {constructor (props) {super(props) this. State = {PDF: null, scale: 1.2}}getChildContext () {
        return {
            pdf: this.state.pdf,
            scale: this.state.scale
        }
    }
    componentDidMount () {
        PDFJS.getDocument(this.props.src).then((pdf) => {
            console.log(pdf)
            this.setState({ pdf })
        })
    }
    render () {
    return (<div className='pdf-context'>{this.props.children}</div>) 
    }
}

PDF.propTypes = {
    src: React.PropTypes.string.isRequired
}

PDF.childContextTypes = {
    pdf: React.PropTypes.object,
    scale: React.PropTypes.number
}

class Page extends React.Component {
    constructor (props) {
        super(props)
        this.state = {
            status: 'N/A',
            page: null,
            width: 0,
            height: 0
        }
    }
    shouldComponentUpdate (nextProps, nextState, nextContext) {
        returnthis.context.pdf ! = nextContext.pdf || this.state.status ! == nextState.status } componentDidUpdate (nextProps, nextState, nextContext) { this._update(nextContext.pdf) }componentDidMount () {
        this._update(this.context.pdf) 
    }
    _update (pdf) {
        if (pdf) {
            this._loadPage(pdf)
        } else {
            this.setState({ status: 'loading' }) 
        }
    }
    _loadPage (pdf) {
        if (this.state.status === 'rendering'|| this.state.page ! = null)return; 
        pdf.getPage(this.props.index).then(this._renderPage.bind(this))
        this.setState({ status: 'rendering' })
    } 
    _renderPage (page) {
        console.log(page)
        let { scale } = this.context 
        let viewport = page.getViewport(scale)
        let { width, height } = viewport
        let canvas = this.refs.canvas
        let context = canvas.getContext('2d')
        console.log(viewport.height, viewport.width)
        canvas.width = width
        canvas.height = height
        
        page.render({
            canvasContext: context,
            viewport
        })
      
        this.setState({ status: 'rendered', page, width, height })
    }
    render () {
        let { width, height, status } = this.state
        return (
            <div className={`pdf-page {status}`} style={{width, height}}>
                <canvas ref='canvas' />
            </div>
        )
    }
}

Page.propTypes = {
    index: React.PropTypes.number.isRequired
}
Page.contextTypes = PDF.childContextTypes

class Viewer extends React.Component {
    render () {
        let { pdf } = this.context
        let numPages = pdf ? pdf.pdfInfo.numPages : 0
        let fingerprint = pdf ? pdf.pdfInfo.fingerprint : 'none'
        let pages = Array.apply(null, { length: numPages })
            .map((v, i) => (<Page index={i + 1} key={`${fingerprint}-${i}`} / >))return (
            <div className='pdf-viewer'>
                {pages}
            </div>
        )
    }
}
Viewer.contextTypes = PDF.childContextTypes
Copy the code

The last step is to call the PDF component. Change the header meta[name=”viewport”] property to zoom in and out freely, and restore the meta tag to unzooming when you exit the PDF page

class previewPDF extends React.Component { constructor (props) { super (props); } // Change the meta to manually scalable when initializing the PDF componentcomponentDidMount(){
        document.querySelector('meta[name="viewport"]').setAttribute("content"."Width = device - width, user - scalable = yes, initial - scale = 0.5, the maximum - scale = 1.2, the minimum - scale = 0.1"); } // Restore meta when component uninstallscomponentWillUnmount(){
        document.querySelector('meta[name="viewport"]').setAttribute("content"."Width = device - width, user - scalable = no, initial - scale = 0.5, the maximum - scale = 0.5, the minimum - scale = 0.5");
        window.location.reload();
    }

    render() {
        let PDF_URL = getQueryString('pdf', this.props.location.search);
        return( <PDF src={PDF_URL}> <Viewer /> </PDF> ); }}Copy the code

——————- What’s New ——————

The React. PropTypes problem

As of React V15.5, React.PropTypes has been moved to another package. React.PropTypes use the prop-types library instead. The use of prop-types is as follows:

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};
Copy the code

Updated PDF component

import React, { Component } from 'react';
import PropTypes from 'prop-types';

exportClass PDF extends Component {constructor (props) {super(props) this. State = {PDF: null, scale: 1.2}} class PDF extends Component {constructor (props) {super(props) this.getChildContext () {
        return {
            pdf: this.state.pdf,
            scale: this.state.scale
        }
    }
    componentDidMount () {
        PDFJS.getDocument(this.props.src).then((pdf) => {
            console.log(pdf)
            this.setState({ pdf })
        })
    }
    render () {
        return (<div className='pdf-context'>{this.props.children}</div>) 
    }
}

// PDF.propTypes = {
//     src: PropTypes.string.isRequired
// }

PDF.childContextTypes = {
    pdf: PropTypes.object,
    scale: PropTypes.number
}

export class Page extends Component {
    constructor (props) {
        super(props)
        this.state = {
            status: 'N/A',
            page: null,
            width: 0,
            height: 0
        }
    }
    // shouldComponentUpdate (nextProps, nextState, nextContext) {
    //     returnthis.context.pdf ! = nextContext.pdf || this.state.status ! == nextState.status // } // componentDidUpdate (nextProps, nextState, nextContext) { // debugger // this._update(nextContext.pdf) // }componentDidMount () {
        this._update(this.context.pdf) 
    }
    _update (pdf) {
        if (pdf) {
            this._loadPage(pdf)
        } else {
            this.setState({ status: 'loading' }) 
        }
    }
    _loadPage (pdf) {
        if (this.state.status === 'rendering'|| this.state.page ! = null)return; 
        pdf.getPage(this.props.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')

        canvas.width = width
        canvas.height = height
        
        page.render({
            canvasContext: context,
            viewport
        })
      
        this.setState({ status: 'rendered', page, width, height })
    }
    render () {
        let { width, height, status } = this.state
        return (
            <div className={`pdf-page {status}`} style={{width, height}}>
                <canvas ref='canvas' />
            </div>
        )
    }
}

// Page.propTypes = {
//     index: PropTypes.number.isRequired
// }
Page.contextTypes = PDF.childContextTypes

export class Viewer extends Component {
    render () {
        let { pdf } = this.context
        let numPages = pdf ? pdf.pdfInfo.numPages : 0
        let fingerprint = pdf ? pdf.pdfInfo.fingerprint : 'none'
        let pages = Array.apply(null, { length: numPages })
            .map((v, i) => (<Page index={i + 1} key={`${fingerprint}-${i}`} / >))return (
            <div className='pdf-viewer'>
                {pages}
            </div>
        )
    }
}
Viewer.contextTypes = PDF.childContextTypes
Copy the code