jsPDF+html2canvas实现html转pdf下载+打印

 原理:将页面的dom元素通过html2canvas转成canvas,通过canvas.toDataURL('image/jpeg', 1.0);返回一个包含图片展示的 数据URL,通过JsPDF将调用 addImage用法插入图片数据,JsPDF通过addPage添加页面,pdf.autoPrint()自动打印, pdf.save(`${title}.pdf`)生成pdf文件。

缺陷:通过html2canvas转化后有缩放,无论怎么调整,感觉都不够高清,大多数场景都能满足,但是和手动创建word文档打印,还是有差距,若用在重要文档上,业务审核肯定不通过,这个时候就要求无缩放打印,下一章写如何用JsPDF无缩放打印


pdf.addimage()是一个可用于在PDF文件上插入图片的函数,它提供了控制图片大小、压缩质量、图片旋转度数等属性。

pdf.addImage(image, format, x, y, width, height, alias, compression, rotation)
参数
1、image:表示要插入的图片资源,可以是图片文件的路径或者base64编码字符串。

2、format:表示要插入的图片格式,包括:‘JPEG’, ‘PNG’, ‘GIF’, ‘BMP’, ‘TIFF’, ‘RAW’, ‘JPEG2000’。

3、x:图片在PDF中的x轴坐标,单位为pt(点)。

4、y:图片在PDF中的y轴坐标,单位为pt(点)。

5、width:图片在PDF中的宽度,单位为pt(点)。

6、height:图片在PDF中的高度,单位为pt(点)。

7、alias(可选):指定图片资源的别名。

8、compression(可选):指定图片的压缩质量,取值为0-1之间的浮点数。

9、rotation(可选):指定图片的旋转角度,取值范围为0-360之间的整数

核心代码如下:

/**
 * 生成pdf、pdf打印
 * @param {*} ele  页面解析后的dom
 * @param {*} printParams 打印配置,内部配置参数如下
 * @param {*} title  文件名称
 * @param {*} type 打印类型
 * @param {*} offset  边距
 */
export const printPreviewPDF = (ele, printParams) => {
  const { title, type, offset = 15, iframDom, scale} = printParams;
  const newDom = ele.cloneNode(true);
  newDom.style.position = 'fixed';
  newDom.style.top = 999999;
  document.body.appendChild(newDom);
  html2canvas(newDom, { dpi: 300, scale: scale || 2 }).then((canvas) => {
    const contentWidth = canvas.width;
    const contentHeight = canvas.height;

    const w = 595.28 - offset * 2;
    const h = 841.89 - offset * 2;
    // 一页pdf显示html页面生成的canvas高度;
    const pageHeight = (contentWidth / w) * h;
    // 未生成pdf的html页面高度
    let remainHeight = contentHeight;
    // pdf页面偏移
    let position = 0;
    // html页面生成的canvas在pdf中图片的宽高(a4纸的尺寸[595.28,841.89])
    const imgWidth = w;
    const imgHeight = (w / contentWidth) * contentHeight;

    const pageData = canvas.toDataURL('image/jpeg', 1.0);
    const pdf = new JsPDF('', 'pt', 'a4');

    // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
    // 当内容未超过pdf一页显示的范围,无需分页
    if (remainHeight < pageHeight) {
      pdf.addImage(pageData, 'JPEG', offset, offset, imgWidth, imgHeight);
    } else {
      while (remainHeight > 0) {
        pdf.addImage(pageData, 'JPEG', offset, position, imgWidth, imgHeight);
        remainHeight -= pageHeight;
        position -= 841.89;
        // 避免添加空白页
        if (remainHeight > 0) {
          pdf.addPage();
        }
      }
    }
    if (type === PRINT_TYPE.CURRENT_PRINT) {
      pdf.autoPrint();
      iframDom.src = pdf.output('datauristring'); // 在iframe中显示,实现当前页面打印
      // 打印
    } else if (type === PRINT_TYPE.DOWNLOAD) {
      // 下载
      pdf.save(`${title}.pdf`);
    } else {
      // pdf.autoPrint();
      // pdf.output('dataurlnewwindow'); --- 这个方法,导致 超过 3页,第4页的时候 页面空白。弃用。
      const link = window.URL.createObjectURL(toBlob(pdf.output('datauristring')));
      const myWindow = window.open(link);
      myWindow.print();
    }
    newDom.remove();
  });
};

你可能感兴趣的:(React,pdf,javascript,前端)