前端将表格页面导出为 PDF 并适配 A4纸张的思路

文章目录


最终效果

这个是原页面

这个是前端处理成 pdf 的效果


技术依赖包

vue2 + element + html2canvas + jsPDF

html2Canvas 官网
jsPDF 官网


优缺点

  • 优点:就是不需要后端处理 pdf 了,原本想着把 domcss 传递给后端让后端生成,奈何后端是 php,解析器不给力(这是后端跟我讲的,有没有懂 php 大佬)
  • 缺点:生成的 pdf 比较糊,而且表格在分页的时候容易分裂,我暂时没有更好的方案

实现思路

  • html 先转换成 canvas ,然后生成图片,最后再将图片转换成 pdf
  • 需要先把页面适配一下 A4 纸张大小,不然下面切割的话会出问题

代码

javascript 复制代码
import html2canvas from 'html2canvas'
import { jsPDF } from 'jspdf'

async handleUploadHTMLPDF() {
  try {
        this.loading.print = true
        const dom: any = document.querySelector('#printContent')
        const query = this.$route.query
        const id = query?.id
        if (dom) {
            html2canvas(dom).then(async canvas => {
                let pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
                let ctx: any = canvas.getContext('2d')
                let a4w = 190
                let a4h = 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
                let imgHeight = Math.floor((a4h * canvas.width) / a4w) // 按A4显示比例换算一页图像的像素高度
                let renderedHeight = 0
                while (renderedHeight < canvas.height) {
                    let page: any = document.createElement('canvas')
                    page.width = canvas.width
                    page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
                    // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
                    page.getContext('2d').putImageData(
                        ctx.getImageData(
                            0,
                            renderedHeight,
                            canvas.width,
                            Math.min(imgHeight, canvas.height - renderedHeight)
                        ),
                        0,
                        0
                    )
                    pdf.addImage(
                        page.toDataURL('image/jpeg', 1.0),
                        'JPEG',
                        10,
                        10,
                        a4w,
                        Math.min(a4h, (a4w * page.height) / page.width)
                    ) // 添加图像到页面,保留10mm边距

                    renderedHeight += imgHeight
                    if (renderedHeight < canvas.height) {
                        pdf.addPage() // 如果后面还有内容,添加一个空页
                    }
                    // delete page;
                }
                // 保存文件
                pdf.save('output.pdf')
                const blob = pdf.output('blob')
                const base64 = await this.blobToBase64(blob)
                // 之后想传给后端 blob 或者 base64 随便你
            })
        }
    } catch (err) {
        console.log(err)
    }
}
blobToBase64 = (blob: Blob): Promise<string> => {
    return new Promise(resolve => {
        const reader = new FileReader()
        reader.onloadend = () => resolve(reader.result as string)
        reader.readAsDataURL(blob)
    })
}

相关推荐
@大迁世界1 分钟前
构建 Next.js 应用时的安全保障与风险防范措施
开发语言·前端·javascript·安全·ecmascript
IT、木易1 小时前
ES6 新特性,优势和用法?
前端·ecmascript·es6
计算机软件程序设计1 小时前
vue和微信小程序处理markdown格式数据
前端·vue.js·微信小程序
指尖时光.1 小时前
【前端进阶】01 重识HTML,掌握页面基本结构和加载过程
前端·html
前端御书房2 小时前
Pinia 3.0 正式发布:全面拥抱 Vue 3 生态,升级指南与实战教程
前端·javascript·vue.js
NoneCoder2 小时前
JavaScript系列(84)--前端工程化概述
前端·javascript·状态模式
晚安7202 小时前
idea添加web工程
java·前端·intellij-idea
零凌林3 小时前
vue3中解决组件间 css 层级问题最佳实践(Teleport的使用)
前端·css·vue.js·新特性·vue3.0·teleport
糟糕好吃3 小时前
用二进制思维重构前端权限系统
前端
拉不动的猪4 小时前
刷刷题17(webpack)
前端·javascript·面试