使用背景:
小菜鸡码农的我在公司负责的移动端项目,是一款web App,因为安卓端和IOS的浏览器对于PDF文件的解析支持不同,所以运用iframe标签等等在安卓都无法实现浏览PDF文件的功能,因此在业务的驱动下,我自己开始封装组件了
官网: https://mozilla.github.io/pdf.js/examples/
放心使用: 参考科普篇 https://blog.csdn.net/goobird/article/details/85673918
现在项目中安装该插件:
npm install pdfjs-dist --save
可以参考官网的文档: https://github.com/mozilla/pdf.js/blob/master/src/display/api.js
pdf.js渲染PDF文件的流程:Fetch pdf (url / buffer) ——> canvas ——> 渲染
//获取canvas实例
setCanvas = (el) => {
this.canvas = el;
}
获取到的el: 就是PDF的渲染元素啦
//使用promise来获取页数
pdfDoc.getPage(num).then((page) =>{
let viewport = page.getViewport({scale: this.state.scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
//将PDF文件转化为canvas context
let renderContext = {
canvasContext: canvas.getContext('2d'),
viewport: viewport
};
let renderTask = page.render(renderContext);
//等待渲染完成
renderTask.promise.then(() =>{
this.setState({
pageRendering: false,
isFirstDisabled: num > 1 ? false : true,
isLastDisabled: num === this.state.Total ? true : false
});
if (this.state.pageNumPending !== null) {
//翻页的新的一页正在加载中
this.renderPage(pageNumPending);
this.setState({
pageNumPending: null
});
}
});
});
1.在PDF文件中,部分中文字体解析不到位,导致文字丢失
原本像右边显示的字体,在安卓浏览器渲染不出来!!
解决方案:
componentDidMount() {
const { src } = this.props;
const { pageNum } = this.state;
pdfjs.getDocument({
url: src,
cMapUrl: 'cmaps/',//加载pdf.js提供的字体文件
cMapPacked: true, // 此参数需要设为true
}).promise.then((pdfDoc_) => {
this.setState({
pdfDoc: pdfDoc_,
Total: pdfDoc_._pdfInfo.numPages
},()=>{
//初始化第一页文件
this.renderPage(pageNum);
});
});
}
在获取文件的函数里加上参数:
cMapUrl: ‘cmaps/’,//加载pdf.js提供的字体文件
cMapPacked: true, // 此参数需要设为true
module: {
rules: [
{
test: /.(woff|woff2|eot|ttf|otf|pdf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:5][ext]'
}
}
],
include: path.join(__dirname, '../src'),
}
]
},
plugins: [
new CopyWebpackPlugin([
{
from: path.join(__dirname, '../node_modules/pdfjs-dist/cmaps/'),
to: path.join(__dirname, '../dist/cmaps'),//这就是使用是引入的路径
},
]),
],
结果不同字体的显示也不会丢失啦!(马赛克是我人为处理的哈哈哈!)
import React, { Component } from 'react';
import pdfjs from 'pdfjs-dist/build/pdf';
import { Button } from 'antd-mobile';
import PropTypes from 'prop-types';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
import styles from './style.less';
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
export class PDF extends Component {
canvas = null;
constructor(props) {
super(props);
this.renderPage = this.renderPage.bind(this);
this.queueRenderPage = this.queueRenderPage.bind(this);
this.onPrevPage = this.onPrevPage.bind(this);
this.onNextPage = this.onNextPage.bind(this);
this.state = {
pdfDoc: null,
Total: 0,
PerviousPage: 1,
LastPage: 1,
pageNum: 1,
pageRendering: false,
pageNumPending: null,
scale: 1,
isFirstDisabled: true,
isLastDisabled: false
};
}
componentDidMount() {
const { src } = this.props;
const { pageNum } = this.state;
pdfjs.getDocument({
url: src,
cMapUrl: 'cmaps/',//加载pdf.js提供的字体文件
cMapPacked: true, // 此参数需要设为true
}).promise.then((pdfDoc_) => {
this.setState({
pdfDoc: pdfDoc_,
Total: pdfDoc_._pdfInfo.numPages
},()=>{
//初始化第一页文件
this.renderPage(pageNum);
});
});
}
//获取canvas实例
setCanvas = (el) => {
this.canvas = el;
}
renderPage(num) {
const canvas = this.canvas;
const {
pdfDoc,
pageNumPending
} = this.state;
this.setState({
pageRendering: true,
});
//使用promise来获取页数
pdfDoc.getPage(num).then((page) =>{
let viewport = page.getViewport({scale: this.state.scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
//将PDF文件转化为canvas context
let renderContext = {
canvasContext: canvas.getContext('2d'),
viewport: viewport
};
let renderTask = page.render(renderContext);
//等待渲染完成
renderTask.promise.then(() =>{
this.setState({
pageRendering: false,
isFirstDisabled: num > 1 ? false : true,
isLastDisabled: num === this.state.Total ? true : false
});
if (this.state.pageNumPending !== null) {
//翻页的新的一页正在加载中
this.renderPage(pageNumPending);
this.setState({
pageNumPending: null
});
}
});
});
//改变页数计算
this.setState({
PerviousPage: num
});
}
queueRenderPage(num) {
if (this.state.pageRendering) {
this.setState({
pageNumPending: num
});
} else {
this.renderPage(num);
}
}
onPrevPage() {
if (this.state.PerviousPage <= 1) {
return;
}
let {PerviousPage} = this.state;
this.setState({
PerviousPage: PerviousPage--
},()=>{
this.queueRenderPage(PerviousPage);
});
}
onNextPage() {
if (this.state.PerviousPage >= this.state.pdfDoc.numPages) {
return;
}
let {PerviousPage} = this.state;
this.setState({
PerviousPage: PerviousPage++
},()=>{
this.queueRenderPage(PerviousPage);
});
}
render() {
const { Total, PerviousPage, isFirstDisabled, isLastDisabled } = this.state;
return (
{PerviousPage}/{Total}
);
}
}
PDF.propTypes = {
src: PropTypes.string.isRequired,
children: PropTypes.object
};
使用: