前端将表格页面导出为 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)
    })
}

相关推荐
念念不忘 必有回响13 小时前
nginx前端部署与Vite环境变量配置指南
前端·nginx·vite
JIngJaneIL13 小时前
篮球论坛|基于SprinBoot+vue的篮球论坛系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·篮球论坛系统
程序猿阿伟15 小时前
《首屏加载优化手册:Vue3+Element Plus项目提速的技术细节》
前端·javascript·vue.js
fruge16 小时前
Vue Pinia 状态管理实战指南
前端·vue.js·ubuntu
sean17 小时前
开发一个自己的 claude code
前端·后端·ai编程
用户214118326360217 小时前
dify案例分享-用 Dify 一键生成教学动画 HTML!AI 助力,3 分钟搞定专业级课件
前端
太过平凡的小蚂蚁19 小时前
Kotlin 协程中常见的异步返回与控制方式(速览)
开发语言·前端·kotlin
咖啡の猫20 小时前
Vue初始化脚手架
前端·javascript·vue.js
晨枫阳20 小时前
uniapp兼容问题处理总结
前端·vue.js·uni-app
何中应21 小时前
如何截取PDF内容为图片
java·开发语言·后端·pdf