上午 10:30,甲方爸爸甩来一句:
“小 X,页面上这块报表我想右键另存为 PDF,能做到不?”
我:
“能,但右键太 low,我给你点按钮直接整页导出,高清矢量,还能分页。”
甲方:
“多久?”
“喝完这杯咖啡给你 demo。”
① 找到要导出的盒子
② 用 html2canvas 拍一张“截图”
③ 把截图按 A4 高度裁成 N 张
④ jspdf 一张一张 addImage,最后 save() 下载
// src/utils/exportPdf.js
import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'
/**
* 导出DOM元素为PDF
* 高端的导出方法只需要采用最简单的办法
* 获取浏览器dom就可以了...
*/
export const exportToPdf = async (element, options = {}) => {
const {
filename = 'document',
scale = 2,
showLoading = true,
showSuccess = true,
showError = true
} = options
// 获取DOM元素
let targetElement
if (typeof element === 'string') {
targetElement = document.querySelector(element)
} else {
targetElement = element
}
if (!targetElement) {
const errorMsg = '未找到要导出的元素'
if (showError) console.error(errorMsg)
throw new Error(errorMsg)
}
try {
// 显示加载提示
if (showLoading) {
console.log('正在生成PDF...')
// 如果使用Element UI,可以这样:this.$message.loading('正在生成PDF...')
}
// 滚动到元素位置
targetElement.scrollIntoView({ behavior: 'smooth' })
// 转换为canvas
const canvas = await html2canvas(targetElement, {
scale: scale,
useCORS: true,
backgroundColor: '#ffffff',
logging: false,
allowTaint: true
})
// 创建PDF
const imgData = canvas.toDataURL('image/png', 1.0)
const imgWidth = 210 // A4宽度(mm)
const imgHeight = (canvas.height * imgWidth) / canvas.width
const pdf = new JsPDF('p', 'mm', 'a4')
let heightLeft = imgHeight
let position = 0
const pageHeight = 297 // A4高度(mm)
// 添加第一页
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
heightLeft -= pageHeight
// 分页处理
while (heightLeft > 0) {
position = heightLeft - imgHeight
pdf.addPage()
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
heightLeft -= pageHeight
}
// 保存文件
pdf.save(`${filename}.pdf`)
// 显示成功提示
if (showSuccess) {
console.log('PDF导出成功!')
// 如果使用Element UI,可以这样:this.$message.success('PDF导出成功!')
}
return true
} catch (error) {
console.error('导出PDF失败:', error)
if (showError) {
console.error('导出失败:', error.message)
}
throw error
}
}
<template>
<div>
<el-button type="primary" @click="download">导出当前报表</el-button>
<div ref="report">……你的表格/图表/一切……</div>
</div>
</template>
<script setup>
import { exportToPdf } from '@/utils/exportPdf'
function download() {
exportToPdf(this.$refs.report, { filename: '月度报表_202509' })
}
</script>
点击按钮→控制台打印“正在生成PDF…”→1 秒后自动下载“月度报表_202509.pdf”。
甲方当场拍板:“尾款现在就付!”
坑 | 解 |
---|---|
图片跨域空白 | html2canvas 加 |
分页被截断文字 | 给每页留 30 mm 页眉页脚,canvas 提前分段(本文 demo 自动分页,简单粗暴) |
字体模糊 | scale 调到 2 以上, retina 屏 3 更佳 |
黑屏 | 确保背景色 |
pdf.setTextColor(200)
+ pdf.text('内部资料', 105, 150, { angle: 45 })
pdf.output('blob')
得到 Blob→FormData→axios 上传阿里云 OSS,返回永久链接。webpack 配置 externals
把 html2canvas & jspdf 走 CDN,gzipped 后业务代码只剩 3 kB,手机 4G 秒开。
“把网页导出成 PDF”听着像 HR 需求,但用对轮子 30 分钟就能交差。
甲方满意,你早下班,代码还零依赖后端。
源码就在上面,复制-粘贴-跑,今晚不加班!
如果帮到你,点个 ⭐ 不过分吧~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。