前言
记录一下最近实现的前端生成pdf的功能,以及遇到的坑和解决方式
由于笔者1年多没碰过react了,之前也比较少使用hooks,实现这个功能也是想复习一下之前的知识,如果有什么写得不好的请指出交流。
正文
安装lib
npm install -S jspdf html2canvas
jspdf+html2canvas, 基本的实现逻辑使用html2canvas将html放入canvas,然后将canvas转成base64的图片,再用jspdf.addImage()将图片放入pdf。
我们的目标实现是将这个功能封装成一个可复用的component,后续使用只需要传入header,content,footer, 就可以生成一份带有页眉页尾的pdf。
index.js
import React, { Component, useState, useMemo, useRef, useEffect } from 'react';
import PdfComponent from '@/components/PdfComponent';
import img from '@/asset/img/三姐妹泉中的西印度海牛,佛罗里达州克里斯特尔里弗国家野生动物保护区.jpg'
import logo from '@/asset/logo/dog.jpg'
import './index.css';
import moment from 'moment';
import mockData from './mockData';
function HeaderComponent(props) {
return <div style={
{ padding: '10px 0' }}>
<img src={logo} />
<span>
Header
</span>
<hr />
</div>
}
function Pdf() {
const pdfRef = useRef(null);
const downloadPdf = () => {
pdfRef.current.downloadPdf();
}
const Content = [
<img id='img' key='img' style={
{ maxHeight: '200px', width: 'auto' }} src={img} />,
...mockData.map((data, ind) => {
return (
<div key={data.id}>
<h3>{data.title}</h3>
{
(ind % 8 === 0) && <img key={'img' + ind} style={
{ maxHeight: '100px', width: 'auto' }} src={img} />
}
<div style={
{
color: 'grey',
}}>
{
data.content.map((content, ind) => (
<p key={ind}>{content}</p>
))
}
</div>
</div>
)
})
]
return (
<>
<h3>
Pdf
</h3>
{/* 按钮 */}
<button onClick={downloadPdf}>Download</button>
<PdfComponent
ref={pdfRef} // 组件ref
plr={23} // 左右边距
keepImgQuality={true} // 是否保持图片质量
scale={4} // 用于让html放大n倍后再转为canvas 用于修改生成pdf的清晰度,越清晰pdf大小会越大
decoratePdf={(pdf, pageTotal, headerSize, footerSize) => { // 装饰pdf,导出pdf对象,用于生成页数之类的修饰信息
pdf.setFontSize(9); // 设置字体大小
const lineHeight = pdf.getLineHeight(); // 获取行高
new Array(pageTotal).fill(0).forEach((item, i) => { // 根据总页数循环添加页码
// set page & date
pdf.setPage(i + 1);
const pageText = (i