jspdf+html2canvas实现前端pdf导出

5,439 阅读2分钟

背景

最近开发项目中遇到一个需求,需要实现pdf下载,查阅了一些资料,在此做以整理。

两个库

jspdf:一个用于在客户端JavaScript中生成PDF的库
htmlcanvas2:html2canvas可以通过纯JS对浏览器端进行截屏

思路就是先使用htmlcanvas2对页面进行截图,再使用jspdf将截图生成pdf文件

安装jspdf和htmlcanvas2

npm install --save htmlcanvas2
npm install --save jspdf

首先使用htmlcanvas2完成对页面的截图,上代码

    import html2Canvas from 'html2canvas'
    let pdfDom = document.getElementById('#pdf')
    // allowTaint: true 表示允许跨越的图片
    html2Canvas(pdfDom, { allowTaint: true }).then((canvas) => {
        document.body.appendChild(canvas)
        // 生成canvas截图,1表示生成的截图质量(0-1)
        let pageData = canvas.toDataURL('image/jpeg', 1)
    })

使用jspdf生成pdf文件

import JsPDF from 'jspdf'
    // new JsPDF接收三个参数,landscape表示横向,(默认不填是纵向),打印单位和纸张尺寸
    let PDF = new JsPDF('landscape', 'pt', 'a4')
    // 第一个20表示内容与纸张左侧的距离,第二个20表示内容与纸张上方的距离
    PDF.text('pdf内容', 20, 20) 
    // 调用addImage方法,pageData表示生成的截图内容,第二个参数表示距纸张左侧的距离,第二个参数表示距纸张上方的距离,第四个参数表示生成截图的image的宽度,第五个参数表示生成截图的image的高度
    PDF.addImage('pageData', 'JPEG', 20, 20, imgCanvasWidth, imgCanvasHeight) 
    // 调用save方法生成pdf文件
    PDF.save('导出pdf' + '.pdf')

生成pdf文件

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

export default {
   install( Vue, options) {
       Vue.prototype.exportPdfFile = function () {
           let pdfDom = document.getElementById('#pdf')
           // allowTaint: true 表示允许跨越的图片
           html2Canvas(pdfDom, { allowTaint: true }).then((canvas) => {
                // a4纸的正常尺寸是宽592.28,高是841.89,这里针对我自己的项目将宽高调换了
                const pageWidth = 841.89
                const pageHeight = 592.28
                // 设置内容的宽高
                const contentWidth = canvas.width
                const contentHeight = canvas.height
                // 默认的偏移量
                let position = 0
                // 设置生成图片的宽高
                const imgCanvasWidth = pageWidth
                const imgCanvasHeight = 592.28 / contentWidth * contentHeight
                let imageHeight = imgCanvasHeight
                // 生成canvas截图,1表示生成的截图质量(0-1)
                let pageData = canvas.toDataURL('image/jpeg', 1)
                // new JsPDF接收三个参数,landscape表示横向,(默认不填是纵向),打印单位和纸张尺寸
                let PDF = new JsPDF('landscape', 'pt', 'a4')
                // 当内容不超过a4纸一页的情况下
                if (imageHeight < pageHeight) {
                  PDF.addImage(pageData, 'JPEG', 20, 20, imgCanvasWidth, imgCanvasHeight)
                } else {
                  // 当内容超过a4纸一页的情况下,需要增加一页
                  while (imageHeight > 0) {
                    PDF.addImage(pageData, 'JPEG', 20, position, imgCanvasWidth, imgCanvasHeight)
                    imageHeight -= pageHeight
                    position -= pageHeight
                    // 避免添加空白页
                    if (imageHeight > 0) {
                      PDF.addPage()
                    }
                  }
                }
                // 调用save方法生成pdf文件
                PDF.save('导出pdf' + '.pdf')
           })
       }
   } 
}