前端导出PDF


最近开发接到需求,要求导出页面dom为PDF的文件,开发中的一些问题在这里做个记录,开发使用vue.js,自行下载JsPdf(html2canvas.js、html2canvas.min.js、jsPdf.debug.js)导入到项目中

// 具体页面引用
import html2canvas from 'html2canvas'

直接上代码(dom)

// 在需要导出的dom div标签加上ref="wordEle",注意不可加在循环的标签内,不然在导出执行js时有错误,这也算是一个坑点吧
//这里还有一个点,跟大家分享一下,也算是一个BUG,导出的PDF内容是会受到当前页面的宽度(浏览器窗口宽度,感兴趣的可以自己试一下F12,调整不同的宽度导出PDF以后,看看内容)影响的
//解决方案可以在 标签内定义一个宽度固定住单位mm,px的话,打印机器打印出来是空白的(猜测跟导出的宽度有关没有深究),本人亲测
<div ref="wordEle" style="width: 245mm;">   
   <div> body 需要导出内容 </div>
</div>

直接上代码(js)

exportFun () {
      let that = this
      const el = this.$refs.wordEle
      let pageData = ''
      const options = {}
      html2canvas(el, options).then((canvas) => {
        pageData = canvas.toDataURL('image/jpeg', 1)
        var contentWidth = el.clientWidth
        var contentHeight = el.clientHeight
        // 一页pdf显示html页面生成的canvas高度;
        var pageHeight = contentWidth / 592.28 * 841.89
        // 未生成pdf的html页面高度
        var leftHeight = contentHeight
        // pdf页面偏移
        var position = 37
        // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        var imgWidth = 595.28
        var imgHeight = 592.28 / contentWidth * contentHeight
        // var pageData = res
        that.YS.YS_jsPdf(() => {
          // eslint-disable-next-line
          let pdf = new jsPDF({unit: 'pt', format: 'a4', compress: true})
          // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
          // 当内容未超过pdf一页显示的范围,无需分页
          if (leftHeight < pageHeight) {
            pdf.addImage(pageData, 'JPEG', 0, position, 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('深圳英之泰学校新生预开户信息表.pdf')
        })
      })
    }

js代码上完了,在这里分享一个BUG(当导出内容分页时,页面被分割的问题),如下图所示:可以看到第二页的内容有一部分被分割到第一页的结尾后面,或者有的是内容连着第一页也有被分割的
在这里插入图片描述
我们来看下jspdf导出的代码分页的那段

//很明显是通过leftHeight(未生成pdf的html页面高度) pageHeight(一页pdf显示html页面生成的canvas高度)来判断是否分页的
          if (leftHeight < pageHeight) {
            pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
          } else {
            while (leftHeight > 0) {
              pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
              leftHeight -= pageHeight
              // position -= 841.89
              // 避免添加空白页
              if (leftHeight > 0) {
                pdf.addPage()
              }
            }
          }

我遇到内容分割的问题在查看了网上的一些方案(把内容做成一页,这样就没有分页内容分割问题),
但是实际业务并数据很多并不允许我这样做,既然导出dom内容分割,于是我就想了一个办法,利用dom的高度和样式 margin-bottom , 把第二页的内容强行压下去行不行呢?(虽然这个办法看起来并不是什么精致的好主意)

//首先给导出的div一个固定的高度,在样式里面设置一下margin-bottom,然后在导出,根据实际的需求自行调整
.body{
  width: 245mm;
  height: 1200px;
  margin-bottom: 60px;
}
<div ref="wordEle" class="">   
   <div> body 需要导出内容 </div>
</div>
//js方法中的position = 37 其实就内容与顶部的距离相当于样式的margin-top:37px,这个值根据的需求自行调整
//有的小伙伴会觉得这个原来这么简单就能解决了,其实我也是自己摸石头过河试出来的
//有的小伙伴会问了你设置的margin-bottom: 60px;这么高,页面会很难看,这里我提一点,其实你可以换个方式,你页面显示的是一套,导出的是另一套(不出现在页面),需要注意的是,jspdf导出对于隐藏的dom是无法导出的

最后展示一下效果图
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值