我的另一片文章,介绍了html2Canvas方式生成PDF

目前可以弄出的效果,自定义生成pdf。其实和canvas画图的过程类似

需求中要求web页面上展示一种UI,生成pdf要word文档那样的简单的。所以一直研究jspdf如何生成pdf

因为html2Canvas截长图不能很好的分页。设置高清截图的时候,pdf有好几大M的内存。受不了。

 

一、vue项目中安装下面的依赖,如果你生成pdf不需要表格可以不安装jspdf-autotablejspdf源码中有table()这个方法,可是我一直调不出来,准确来说传参一直没传对,

就用jspdf-autotable)

npm install jspdf -S
npm install jspdf-autotable -S

二、需要解决中文乱码问题

 (window系统)直接在自己电脑的C:\Windows\Fonts下找一种字体(.ttf文件)

步骤这位博主写了

三、

我的项目是vue-cli3创建的,我把生成的字体js文件放在了public文件夹,测试生成pdf的就一个.vue文件

(这里有一个问题,因为字体文件有10几兆大小,当打包后,线上访问,需要优化首次加载速度,异步加载之类的。)我没有解决用户快速点击页面到达需要生成PDF的功能那里,如何更好的提醒用户,相关组件未加载成功,不能生成PDF。主要弄一个类似进度条的东西,提醒用户该字体文件加载成功没。

1)html

<template>
  <div>
    <table id="my_table_1" border="1">
      <thead>
      <tr>
        <th>xx</th>
        <th>dabao</th>
        <th>熊猫</th>
        <th>国宝</th>
      </tr>
      </thead>
      <tbody>
      <tr>
        <td>其他事件</td>
        <td>开发阶段</td>
        <td>任务阶段</td>
        <td>测试</td>
      </tr>
      <tr>
        <td colspan="4">无数据</td>
      </tr>
      <tr>
        <td rowspan="3">人员</td>
        <td>姓名</td>
        <td>学历</td>
        <td>年龄</td>
      </tr>
      <tr>
        <td>王五</td>
        <td>无</td>
        <td>2</td>
      </tr>
      <tr>
        <td>赵六</td>
        <td>无</td>
        <td>2</td>
      </tr>
      <tr>
        <td>新数据</td>
        <td>王五</td>
        <td>无</td>
        <td>2</td>
      </tr>
      </tbody>
    </table>
  </div>
</template>

 

2)js代码

<script>
import autoTable from 'jspdf-autotable'

import font from '../../../public/fonts/STZHONGS-normal'
import PDFCustom from 'jspdf'
export default {
  name: 'TableToPDF',
  data () {
    return {
      subjectFundInfoList: [
       "填表说明","询费的管理按照国家及军队执行执行执行费,无询费的管理按照国家及军队执行执行执行费,主要包括:",
        "(1)材询费的管理按照国家及军队执行执行执行过程中消耗的各种原材料询费的管理按照国家及军队执行执行执行询费的管理按照国家及军队执行执行执行用。",
        "(2)测询费的管理按照国家及军队执行执行执行指在课询费的管理按照国家及军队执行执行执行究、询费的管理按照国家及军队执行执行执行费用。",
        "(3)差询费的管理按照国家及军队执行执行执行作交流费询费的管理按照国家及军队执行执行执行的会议费用,以及开展科学实询费的管理按照国家及军队执行执行执行学术交流" +
        " 国际合作交流等询费的管理按照国家及军队执行执行执行费,询费的管理按照国家及军队执行执行执行邀请国内外专家、学者和有关人员参加会议发生的城市间交通费、国际旅费," +
        " 可以在此项经费中列支。应按照军队会议费管理有关规定,严格执行军队差旅费管理规定,控制出询费的管理按照国家及军队执行执行执行准类别。",
        "(4)询费的管理按照国家及军队执行执行执行/知识产权事务费:是指需要询费的管理按照国家及军队执行执行执行料费、稿费、文询费的管理按照国家及军队执行执行执行具软件购买费、专利申请等费用 。" +
        "可列支询费的管理按照国家及军队执行执行执行费的管理按照国家及军队执行执行执行询费的管理按照国家及军队执行执行执行。",
        "(5)劳务费:是询费的管理按照国家及军队执行执行执行博士后、访问学者以及询费的管理按照国家及军队执行执行执行助人员等的劳务询费的管理按照国家及军队执行执行执行费开支标准,"+
        "参照当地科学研究和技术服务询费的管理按照国家及军队执行执行执行担的工作任务确询费的管理按照国家及军队执行执行执行支标准询费的管理按照国家及军队执行执行执行," +
        "博士询费的管理按照国家及军队执行执行执行平。",
        "(6)询费的管理按照国家及军队执行执行执行询费的管理按照国家及军队执行执行执行究和管理的相关工作人员。" +
        "询费的管理按照国家及军队执行执行执行询费的管理按照国家及军队执行执行执行。"
      ]
    }
  },
  methods: {
    createTablePdf () {
      var pdf = new PDFCustom('p', 'pt', 'a4')
      // 自定义字体
      pdf.addFileToVFS('STZHONGS-normal.ttf', font)
      pdf.addFont('STZHONGS-normal.ttf', 'STZHONGS', 'normal')
      pdf.setFont('STZHONGS')

      pdf.setFontSize(20)
      pdf.text('表格pdf', this.setTextCenter(pdf, 3.5), 60)

      const options = {
        startY: 70, // 表格距离顶部的距离
        theme: 'grid',
        tableWidth: 'auto',
        columnWidth: 'auto',
        styles: {
          overflow: 'linebreak',
          font: 'STZHONGS', // 设置中文
          fontSize: 10,//默认字体大小
          color: '#000'
        },
        columnStyles: {
          0: {fontWeight:'bold',textColor:'#333383',valign:'middle',halign:"center",},
          1: { cellWidth: 100,fontSize:15,fontWeight:'normal'},
          2: { cellWidth: 100,fontSize:15,fontWeight:'bold',halign:"center",}
        },
        headStyles: { // 头部
          fillColor: [255, 255, 255],
          textColor:'#333333',// 头部字体设置为白色可以隐藏字体、或者<th>标签内容为空,单head的高度还是占的。目前还设置不了头部的高度
        }
      }

      if (pdf.autoTableHtmlToJson) {
        var jianbiao = pdf.autoTableHtmlToJson(document.getElementById('my_table_1'))
        pdf.autoTable(jianbiao.columns, jianbiao.data, options)
      }else {
        console.log('无法生成table表格数据')
      }


      pdf.setFont('STZHONGS')
      pdf.setFontSize(10)
      pdf.setTextColor(105,105,105);//设置字体颜色
      let hNum =0;
      for (let i=0;i<this.subjectFundInfoList.length;i++){
        var lines = pdf.splitTextToSize(this.subjectFundInfoList[i],43 * 12);//自动换行,43个字一行
        // console.log(i,'(x,y)',40,320 + (hNum * 12))
        pdf.text(lines,40,320 + (hNum * 12)+ 10)
        hNum += lines.length
      }


      pdf.save('pdfExample.pdf')
      var buffer = pdf.output('datauristring')// 转base64
      var myfile = this.dataURLtoFile(buffer, '测试.pdf')	// 转文件流,可传给后台
      console.log('文件', myfile.name)
    },

    // 文本居中的x轴距离
    setTextCenter (pdf, txtLength) {
      var fontSize = pdf.getFontSize()
      // Get page width
      var pageWidth = pdf.internal.pageSize.width
      const txtWidth = txtLength * fontSize / pdf.internal.scaleFactor
      return (pageWidth - txtWidth) / 2
    },
    // 数据流转File
    dataURLtoFile (dataUrl, fileName) {
      var arr = dataUrl.split(','); var mime = arr[0].match(/:(.*?);/)[1]
      var bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n)
      // console.log('文件后缀,类型',mime)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], fileName, { type: mime })
    }
  }
}
</script>

然后我是在父组件Index.vue调用 createTablePdf()方法。

注意

① jspdf-autotable 一定要引入,在pdf.autoTableHtmlToJson() 和 pdf.autoTable()时需要,否则这两个方法不存在。它是被隐式调用。table数据的时候,有格式的话要在html的table中写好cell的占行colspan和rowspan,其他属性好像读不到。

②文本插入不会自动换行。所有数据会自动换页,需要定位放置好数据。一行规定好几个字(小于  页宽 / 字体大小),我这里是写死43个字。

③如果要传文件给后台,需要转码(代码中已经给出来了)。

 

页眉页脚 那些就自己去查吧!!!

 

Logo

前往低代码交流专区

更多推荐