# jspdf生成Pdf文档
项目需要生成pdf文件,由于对图表样式要求较高,决定放在前端实现。
查询相关资料,发现多采用jspdf + html2canvas实现。
# jspdf安装使用
# 安装
npm install jspdf
# 常用api
- text(text, x, y, options, transform)
添加文字 - setFontSize(size) 设置字体大小
 - addImage(imageData, format, x, y, width, height, alias, compression, rotation)
添加图片 - addPage()
添加新页面 - fromHTML(source, x, y, options) 添加html元素
 - save()
生成pdf 
# 使用
- 直接写入文本
// Default export is a4 paper, portrait, using milimeters for units var doc = new jsPDF() doc.text('Hello world!', 10, 10) doc.save('a4.pdf') - 使用图片
var imgData = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4ge....../2Q=='; var doc = new jsPDF(); doc.setFontSize(40); doc.text(35, 25, "Octonyan loves jsPDF"); doc.addImage(imgData, 'JPEG', 15, 40, 180, 180); - 使用html生成的pdf可以自动分页,但是显示效果很差。
var doc = new jsPDF(); // We'll make our own renderer to skip this editor var specialElementHandlers = { '#editor': function(element, renderer){ return true; } }; // All units are in the set measurement for the document // This can be changed to "pt" (points), "mm" (Default), "cm", "in" doc.fromHTML($('#render_me').get(0), 15, 15, { 'width': 170, 'elementHandlers': specialElementHandlers }); 
# 使用html2canvas
# 安装
npm install html2canvas
# 使用
html2canvas(document.querySelector("#capture")).then(canvas => {
  // do sth
});
# 联合使用生成pdf
let report = document.getElementById('report');
html2canvas(report)
  .then(canvas => {
    // 渲染完成时调用的
    let contentWidth = canvas.width;
    let contentHeight = canvas.height;
    // 一页pdf显示html页面生成的canvas高度;
    let pageHeight = contentWidth / 841.89 * 592.28;
    // 未生成pdf的html页面高度
    let leftHeight = contentHeight;
    // 页面偏移
    let position = 0;
    // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
    let imgWidth = 841.89;
    let imgHeight = 841.89 / contentWidth * contentHeight;
    let pageData = canvas.toDataURL('image/jpeg', 1.0);
    let pdf = new jsPDF('l', 'pt', 'a4'); // l:横向  p:纵向
    // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
    // 当内容未超过pdf一页显示的范围,无需分页
    if (leftHeight < pageHeight) {
      pdf.addImage(pageData, 'JPEG', 26, 43, imgWidth, imgHeight);
    } else {
      while (leftHeight > 0) {
        pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
        leftHeight -= pageHeight;
        position -= 592.28;
        // 避免添加空白页
        if (leftHeight > 0) {
          pdf.addPage();
        }
      }
    }
    let reportName = this.reportData.name;
    pdf.save(reportName + '.pdf');
  });
实际使用时这样分页的效果还是不好,我是对每一个页面设置一个id,通过递归遍历生成pdf,效果完美。