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