纯前端html导出pdf--分页+不分页--html2canvas+jsPDF

前言

最近在项目中,有一个导出pdf功能,需要纯前端来实现,调研了多种pdf导出方式,最终决定使用html2canvas+jsPDF来实现需求。

本文就简单介绍一下html2canvas+jsPDF导出pdf的实现,网上大部分实现导出pdf都是以分页为主的,本文还将附上不分页导出pdf的实现方法。(只附js代码)

html2canvas+jsPDF导出pdf原理:通过html2canvas将遍历页面元素,并渲染生成canvas,然后将canvas图片格式添加到jsPDF实例,生成pdf。

安装:

npm install html2canvas --save

npm install jsPDF --save

配置:

main.js文件里面配置(引入、挂载)

import html2canvas from 'html2canvas'
import jsPDF from 'jsPDF '
Vue.prototype.html2canvas = html2canvas
Vue.prototype.jsPDF = jsPDF 

或者--------------------------------------------------------------------------------

index.html页面直接引入js文件:

<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/jspdf/1.3.4/jspdf.debug.js"></script>

导出pdf按a4纸大小分页处理:// 下载pdf完整方法

downPdf () {
注意:生成的pdf只有页面窗口可见的区域,有滚动条的下面没有生成出来(要注意这里是一个坑)
坑:如果截取是body的这个层级,而刚好body设置了overflow: hidden;那超出的部分是永远截取不到的,因为这个节点的dom高就是窗口可见的高度,并不包含滚动条多出来的部分。
解决办法:只需要在导出之前将overflow:auto设置成visible(默认即可);
        导出pdf后再设置回去。

     // 导出之前将dom的overflow:auto设置成visible    
   this.$('#boardPdf').css({'overflow-y': 'visible', 'height': 'auto'})
    this.$('#app').css({'overflow-y': 'visible', 'height': 'auto'})
    this.$('body').css({'overflow-y': 'visible', 'height': 'auto'})

    // eslint-disable-next-line
    html2canvas(document.querySelector('#boardPdf'), {
        scale: 2,
        onrendered: function (canvas) {
            var contentWidth = canvas.width
            var contentHeight = canvas.height
            // 一页pdf显示html页面生成的canvas高度;
            var pageHeight = contentWidth / 592.28 * 841.89
            // 未生成pdf的html页面高度
            var leftHeight = contentHeight
            // pdf页面偏移
            var position = 0
            // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
            var imgWidth = 595.28
            var imgHeight = 592.28 / contentWidth * contentHeight
            var pageData = canvas.toDataURL('image/jpeg', 1.0)
            // eslint-disable-next-line
            var pdf = new jsPDF('', 'pt', 'a4')
            // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            // 当内容未超过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 -= 841.89
                    // 避免添加空白页
                    if (leftHeight > 0) {
                        pdf.addPage()
                    }
                }
            }
       // 导出pdf文件命名
            pdf.save('report_pdf_' + new Date().getTime() + '.pdf')
        },
        background: '#0B1A48'
    })
  // 导出pdf后,将dom原本的属性设置回去
    this.$('#boardPdf').css({'overflow-y': 'auto', 'height': '100%'})
    this.$('#app').css({'overflow-y': 'auto', 'height': '100%'})
    this.$('body').css({'overflow-y': 'auto', 'height': '100%'})
}

导出pdf自适应大小不分页处理:

// 下载pdf完整方法
downPdf () {
    // 生成的pdf只有页面窗口可见的区域,有滚动条的下面没有生成出来,需在生成PDF前,改overflow属性auto为visible
    this.$('#boardPdf').css({'overflow-y': 'visible', 'height': 'auto'})
    this.$('#app').css({'overflow-y': 'visible', 'height': 'auto'})
    this.$('body').css({'overflow-y': 'visible', 'height': 'auto'})
    // 获取dom高度、宽度
    var shareContent = document.querySelector('#boardPdf')
    var width = shareContent.offsetWidth / 4
    var height = shareContent.offsetHeight / 4
    let _this = this
    // eslint-disable-next-line
    html2canvas(document.querySelector('#boardPdf'), {
        onrendered: function (canvas) {
            var context = canvas.getContext('2d')
            context.mozImageSmoothingEnabled = false
            context.webkitImageSmoothingEnabled = false
            context.msImageSmoothingEnabled = false
            context.imageSmoothingEnabled = false
            var pageData = canvas.toDataURL('image/jpeg', 1.0)
            var img = new Image()
            img.src = pageData
            img.onload = function () {
                // 获取dom高度、宽度
                img.width = img.width / 2
                img.height = img.height / 2
                img.style.transform = 'scale(0.5)'
                if (width > height) {
                    // 此可以根据打印的大小进行自动调节
                    // eslint-disable-next-line
                    var pdf = new jsPDF('l', 'mm', [
                        width * 0.505,
                        height * 0.545
                    ])
                } else {
                    // eslint-disable-next-line
                    var pdf = new jsPDF('p', 'mm', [
                        width * 0.505,
                        height * 0.545
                    ])
                }
                pdf.addImage(
                    pageData,
                    'jpeg',
                    0,
                    0,
                    width * 0.505,
                    height * 0.545
                )
                pdf.save(_this.boardNameTitle + '.pdf')
            }
        },
        background: '#0B1A48'
    })
  // 导出pdf后,将dom原本属性设置回去
    this.$('#boardPdf').css({'overflow-y': 'auto', 'height': '100%'})
    this.$('#app').css({'overflow-y': 'auto', 'height': '100%'})
    this.$('body').css({'overflow-y': 'auto', 'height': '100%'})
}

转载于:https://www.cnblogs.com/candy-xia/p/11155754.html 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值