小程序开发|小程序制作|小程序开发网

搜索

vue页面生成pdf且避免分页截断处理

2022-5-9 13:54| 发布者: admin| 查看: 734| 评论: 5

摘要: 要求按A4纸大小生成pdf,支持分页且内容不被截断使用html2canvas和jspdf插件实现通过html2canvas将HTML页面转换成图片,然后再通过jspdf将图片生成为pdf文件一、添加依赖模块npm install html2canvas --savenpm inst

要求按A4纸大小生成pdf,支持分页且内容不被截断

  • 使用html2canvas和jspdf插件实现
  • 通过html2canvas将HTML页面转换成图片,然后再通过jspdf将图片生成为pdf文件

一、添加依赖模块

npm install html2canvas --save
npm install jspdf --save

二、创建pdf.js全局函数文件

// 创建 pdf.js// 引入依赖import Vue from 'vue'import html2canvas from 'html2canvas'import JsPDF from 'jspdf'const PDF = {}PDF.install = function (Vue, options) {  /**   * targetDom: 需要打印的dom对象   * name:pdf的名字   * callback: 回调函数   */  Vue.prototype.$createPdf = function (targetDom, name, callback) {    let cloneDom = targetDom.cloneNode(true)    cloneDom.style.width = targetDom.scrollWidth + 'px'    cloneDom.style.height = targetDom.scrollHeight + 'px'    cloneDom.style.background = '#FFFFFF'    document.body.appendChild(cloneDom)    let scale = 2    html2canvas(copyDom, {      scale: scale, // 提升画面质量,但是会增加文件大小      useCORS: true, // 允许跨域图片 当图片是链接地址时,需加该属性,否组无法显示图片      imageTimeout: 0, // 图片加载延迟,默认延迟为0,单位毫秒      height: targetDom.scrollHeight, // canvas的高度设定      width: targetDom.scrollWidth, // canvas的宽度设定      dpi: window.devicePixelRatio * scale, // 将分辨率提高到特定的DPI    }).then(canvas => {      document.body.removeChild(cloneDom)      // a4纸的尺寸[592.28,841.89]      const A4_WIDTH = 592.28      const A4_HEIGHT = 841.89      let contentWidth = canvas.width      let contentHeight = canvas.height      let pageData = canvas.toDataURL('image/jpeg', 0.6)      // 一页pdf html页面生成的canvas高度;      let pageHeight = contentWidth / A4_WIDTH * A4_HEIGHT      // 未生成pdf的html页面高度      let leftHeight = contentHeight      // 页面偏移      let position = 0      // a4纸的尺寸[592.28,841.89],html页面生成的canvas在pdf中图片的宽高      let imgWidth = A4_WIDTH      let imgHeight = A4_WIDTH / contentWidth * contentHeight      // 设置pdf的尺寸,pdf要使用pt单位 已知 1pt/1px = 0.75   pt = (px/scale)* 0.75      let pdf = new JsPDF('', 'pt', 'a4')      // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度      // 当内容未超过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 -= A4_HEIGHT          // 避免添加空白页          if (leftHeight > 0) {            pdf.addPage()          }        }      }      // 直接下载      // pdf.save(name + '.pdf')       // base64转成文件      let buffer = pdf.output('datauristring')      let myfile = dataURLtoFile(buffer, name)      callback(myfile)    })  }}Vue.use(PDF)export default PDF
const dataURLtoFile = (dataUrl, fileName) => {  let arr = dataUrl.split(',')  let mime = arr[0].match(/:(.*?);/)[1]  let bstr = atob(arr[1])  let n = bstr.length  let u8arr = new Uint8Array(n)  while (n--) {    u8arr[n] = bstr.charCodeAt(n)  }  return new File([u8arr], fileName, { type: mime })}

三、在页面上使用

// html 
......
// jsvm.$nextTick(async () => { let target = vm.$refs.targetDom vm.$createPdf(target, '文件名', async (file) => { // file对象 })})

四、处理分页被截断问题

1、最简单的就是不截断pdf

将DOM转换为canvas并将pdf的宽高设置为canvas的宽高,再将canvas转为图片,实例化jspdf,将内容图片完整的放在pdf中

2、固定每页pdf大小为A4纸大小且内容不能给隔断

在保持网页的宽高比以及pdf每页的大小(A4)的情况下,dom下元素越多,越可能出现生成多页pdf的情况,就很容易出现一个dom元素被截断分散在两页pdf里
两种思路:
1)每页pdf中的元素以及高度固定,保证在分割的位置不会阶段dom元素,不过这个想法很快放弃,因为项目上需要被生成的dom区域的结构、高度都不固定
2)不依赖布局,给页面上的子元素添加标识, 根据动态计算子元素所在的高度计算出一个位置插入空白高度

// html示例: 
处理后:


五、踩坑点

1、滚动截屏

由于html元素过多,页面上可滑动查看,此时 元素width≠元素scrollWidth , 元素height≠元素一开始的想法是把目标元素的width,height赋值为scrollWidth,scrollHeight,但这样会导致页面会闪烁

    targetDom.style.width = targetDom.scrollWidth + 'px'    targetDom.style.height = targetDom.scrollHeight + 'px'

优化:把目标元素copy下来,html2canvas中引入cloneDom

  let cloneDom = targetDom.cloneNode(true)  cloneDom.style.width = targetDom.scrollWidth + 'px'  cloneDom.style.height = targetDom.scrollHeight + 'px'  cloneDom.style.background = '#FFFFFF'  document.body.appendChild(cloneDom)
2、截屏区域有跨域图片

配下参数即可即:

useCORS: true   允许加载跨域图片

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

鲜花

握手

雷人

路过

鸡蛋
发表评论

最新评论

引用 EW88888 2023-6-17 10:12
不能复制!大哥
引用 北极圈的瓜 2023-3-13 22:52
楼主有导出的pdf带目录的吗?
引用 蠡湖冲 2023-2-7 19:22
怎么能联系到您 我这一直不成功 还是有隔断 真是头疼 插入的高度不对 找不到
引用 FY么事 2022-10-16 23:55
博主能给份完整的代码吗?
引用 yangyuan 2022-9-10 15:18
copyDom、scale、dataURLtoFile报错

查看全部评论(5)

返回顶部