这里介绍的方案有两个: 1.html2canvas + jsPDF 2.pdfMake
(1)首先html2canvas + jsPDF这种方案主要采取的思路是先采用html2canvas来进行截图,截取后才通过计算每页高度的方式来进行裁剪进行分页,最后通过jsPDF来合成图片
代码:
public exportPDF(){
// 要输出的 PDF 每页的宽高尺寸,单位是 pt
let pageWidth = 592.28
let pageHeight = 841.89
var title=parseInt(document.getElementsByClassName('ag-header-row')[0].style.height.slice(0,-2))+document.getElementById('tt-grid-content').offsetHeight;
//表头那部分高度
var titleHeight = 592.28/( this.gridDataWrapper.nativeElement.offsetWidth ) * title;
//列表每行的高度
var cellHeight = 592.28/(this.gridDataWrapper.nativeElement.offsetWidth) * 48;
let page=0;
//第一页
//每条数据的索引
let number=0
//每页添加空以后 给下一页造成的高度
let shengHeight = 0;
var tag =true
this.rowData.forEach((element,index) => {
//第一页时执行
if(page==0){
//减去表头高度后,计算每页能最多存放的记录数
number= Math.floor((841.89 - titleHeight) / cellHeight)
if(index ==number){
//当达到最大记录数以后 添加个空记录,用于分页时防止数据分割
this.rowData.splice(number,0,{})
//记录空记录给下一页表的顶部造成的高度
shengHeight = cellHeight-(841.89 -titleHeight -cellHeight*number)
page=1
}
}else{
//获取上一页给本页顶部造成的高度
let pageNumber = Math.floor((841.89 - shengHeight) /cellHeight)
//本页刚开始的时候就执行 ,这里不放在下面的if里面是因为 index的最大值是一开始this.rowData的长度 而不是操作后的长度 所以到最后的时候 index是不会等于pageNumber+number+1
if(tag){
this.rowData.splice(pageNumber+number+1,0,{});
tag=false
}
if(index ==(pageNumber+number+1)){ //当到达本页数据的最大值的时候 就开始为下一页的做数据预处理
tag=true
shengHeight = cellHeight-(841.89 -shengHeight -cellHeight*pageNumber)
number = pageNumber+number+1;
}
}
});
this.gridDataComponent.gridApi.setRowData(this.rowData)
this.html2CanvasFun()
}
private html2CanvasFun(){
html2canvas(this.gridDataWrapper.nativeElement).then((canvas)=>{
console.log(canvas)
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一页pdf显示html页面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
console.log(pageHeight)
//未生成pdf的html页面高度
var leftHeight = contentHeight;
//页面偏移
var position = 0;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28/contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new jsPDF('', 'pt', 'a4');
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight );
} else {
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白页
if(leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save('aaaa.pdf');
})
}
(2)pdfMake这种是采取数据的方式导出
文档:
https://pdfmake.github.io/docs/document-definition-object/headers-footers/
因为pdfMake不支持中文字体,固自己需要设置字体
//配置PDF的字体
//请求取本地字体
let normal = this.http.get('/assets/font/Semibold.ttf',{responseType: 'blob'});
let bold = this.http.get('/assets/font/Semibold.ttf',{responseType: 'blob'});
let italics = this.http.get('/assets/font/Semibold.ttf',{responseType: 'blob'});
let bolditalics = this.http.get('/assets/font/Semibold.ttf',{responseType: 'blob'});
let base64data:any =[];
Observable.zip(normal,bold,italics,bolditalics).subscribe((res: Array<Blob>) =>{
res.forEach((fontValue)=>{
//二进制转base64
let fileReader = new FileReader();
fileReader.readAsDataURL(fontValue);
fileReader.onload = function() {
let resule: any = fileReader.result;
let data = resule.substring(resule.indexOf(','));
base64data.push(data)
}
//把字体转成base64的格式后才能识别
fileReader.onloadend =()=>{
if(base64data.length ==4){
pdfMake.vfs = {
normal:base64data[0],
bold:base64data[1],
italics:base64data[2],
bolditalics:base64data[3],
};
pdfMake.fonts = {
fonts:{
normal:'normal',
bold:'bold',
italics:'italics',
bolditalics:'bolditalics'
}
}
}
}
});
});复制代码