vue实现打印PDF功能 - html2Pdf.js

踩坑预警

最近更新已经三年前的事情了,将近四百多个问题还未close(重复的问题也挺多的) 官网地址

安装操作

js 复制代码
npm install --save html2pdf.js 
or
npm install --save html2pdf.js -- force
or
cnpm install --save html2pdf.js 

实现直接下载保存PDF操作

可以通过html布局好了,直接打印下载

js 复制代码
import html2pdf from 'html2pdf.js';
let tableElement = document.querySelectorAll('table')
html2pdf().from(tableElement).save(filename);

踩坑历程

要求: 我这边是纯表格的打印操作,但是要求是分页的时候每个表格都是需要携带表头,表格内的图片需要展示

踩坑一: 网络图片无法展示

翻阅了源码开发者上别人提的Issues中发现,这玩意html2canvas处理的时候只能支持base64,虽然有人说可以配置 html2canvas: {scale: 2, useCORS: true},可以解决【但是我测试不行,开发者提议使用base64】

js 复制代码
let imageUrl = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
let image = new Image();
//解决跨域问题
image.setAttribute('crossOrigin', 'Anonymous');
image.src = imageUrl
//image.onload为异步加载
let base64Datas = []
image.onload = () => {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    var context = canvas.getContext('2d');
    context.drawImage(image, 0, 0, image.width, image.height);
    var quality = 0.8;
    //这里的dataurl就是base64类型
    var dataURL = canvas.toDataURL("image/jpeg", quality);//使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
    //数组存放图片base64
    base64Datas.push(dataURL);
    //递归执行图片url转base64        
}

踩坑二: 表头没办法在分页后的自动携带上(printJS这个插件就相当不错,可太傲娇)

这个也是我搞了好久的地方,一开始在Issues中发现添加页码的方式想法去添加表头,如

js 复制代码
 html2pdf().from(tableElement).set(options).toPdf().get('pdf').then(function (pdf) {
    console.log(pdf)
    // paf.table({html: thead})
  }).save(filename);

在,then做PDF的操作,打印PDF暴露出来的API方法中改哪个都油盐不进,一点变化都没有,放弃了,运用固定住表格里的数据高度固定,动态去插入表头进去每个数据中,实现现有表头功能

javascript 复制代码
 const clonedThead = tableElement.querySelector('thead').innerHTML;
  let tbodyList = tableElement.querySelectorAll('tbody');
  console.log(tbodyList)
  tbodyList.forEach((item,index) => {
    if( index % 5 === 0 && index > 0) {
      item.insertAdjacentHTML('afterbegin', '<div style="padding-top: 20px">'+clonedThead+'</div>');
    }
  })

踩坑三: 分页出现截断内容

  1. 配置options 解决分页问题:
javascript 复制代码
const options = {
    margin: 10,
    html2canvas: { 
      scale: 2 
    },
    jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait'},
    pagebreak: {  mode: ['avoid-all', 'css', 'legacy'] },
}
  1. 样式控制

page-break-inside: avoid 可以保留完整的页面

page-break-before: always 可以另起新的一页

从源码发现可以添加类 html2pdf__page-break 进行换页

css 复制代码
//对表格内容保持完整性
.td {
    min-width: 60px;
    text-align: center;
    word-wrap: break-word;
    word-break: break-all;
    border: 1px solid #000;
}

3. 浑身解数之后发现还是会保留一点第二页的数据在第一页中,这种情况有可能是html2canvas画的canvas和设置的A4纸的大小有关了

解决: 我这边运用了插入表头的时候增加个paddingTop的高度可以解决

printJS 打印使用

挺好用的,以上的要求基本能符合需求的开发要求,可惜开源博主在Issues中说我只专注打印开发,如果需要直接下载可以用别的插件很好支持,这边就专注于打印功能。 很显然有点满足不了我多表格区分下载的实现。他这个只支持于单个pdf导出打印预览,有实现过的小伙伴欢迎评论给出兼容的解决方案【【根据HTML可解决直接下载多个PDF】】

javascript 复制代码
// 与html2Pdf.js 区别在的是样式需要单独配置进插件中,无法识别html里的样式,
// 如果需要分页可以根据踩坑三中的样式控制操作,并且图片无需转成base64,
// 我要处理的图片出现跨域问题,在这个插件是不存在这个问题,直接自动处理网络图片
// 附上实现方案
setTimeout(() => {
    printJS({
      printable: 'print', // 要打印的id
      type: 'html',
      header: '',
      style: `@page{size:auto;margin: 0cm 1cm 0cm 1cm;}
      .store-img-stock {
        display:block;
        padding:20px;
        width: 260px;
        height: 260px;
      }
      .s-placeholder{ visibility: hidden; }
      @media print {
        body {
          -webkit-print-color-adjust: exact;
          -moz-print-color-adjust: exact;
          -ms-print-color-adjust: exact;
          print-color-adjust: exact;
        }
      }
      .hidden-border-bottom {
        border-bottom: none;
        border-top: none;
      }
      .thead-th {
        background-color: #333586 !important;
        color: #fff !important;
      }
      .empty-height {
        max-height: 50px;
      }
      .height-20 {
        height: 16px;
      }
      .store-table-a1 {
        margin-bottom: 20px;
        page-break-before: always;
      }
      .store-table-a1 td {
        min-width: 60px;
        text-align: center;
        word-wrap: break-word;
        word-break: break-all;
        border: 1px solid #000;
      }
      .store-table th {
        height: 35px;
        border: 1px solid #000;
      }
      .hidden-border {
        border: none !important;
      }
      ` // 去除页眉页脚
    })
  }, 500)
相关推荐
卸任10 小时前
Vibe coding工具使用心得
前端·ai编程
brien911 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance11 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M11 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写11 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李11 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易12 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马12 小时前
前沿视界
前端
kyriewen12 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易12 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员