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

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端