当前位置: 首页 > news >正文

react+html2canvas+jspdf将页面导出pdf

主要使用html2canvas+jspdf
1.将前端页面导出为pdf
2.处理导出后图表的截断问题

export default function AIReport() {const handleExport = async () => {try {// 需要导出的内容idconst element = document.querySelector('#AI-REPORT-CONTAINER');if (!element) {message.error('未找到要导出的内容');return;}message.loading({ content: '正在导出PDF...', key: 'export' });// 使用html2canvas生成整个报告的画布const canvas = await html2canvas(element as HTMLElement, {scale: 2, // 提高清晰度useCORS: true,allowTaint: true,backgroundColor: '#ffffff',logging: false,});// 创建PDF对象const pdf = new jsPDF({orientation: 'p', // 纵向unit: 'pt', // 使用点作为单位format: 'a4', // A4纸张});// 获取A4页面尺寸const a4Width = pdf.internal.pageSize.getWidth();const a4Height = pdf.internal.pageSize.getHeight();// 计算等比例下A4高度对应的canvas高度const a4HeightInCanvas = Math.floor((canvas.width / a4Width) * a4Height);// 获取canvas的总高度let leftHeight = canvas.height;// PDF页面偏移量let position = 0;// 创建临时canvas用于分页const tempCanvas = document.createElement('canvas');const ctx = tempCanvas.getContext('2d');// 递归处理每一页const processNextPage = () => {if (leftHeight <= 0) {// 完成所有页面处理,保存并下载PDFconst pdfOutput = pdf.output('blob');const url = URL.createObjectURL(pdfOutput);const link = document.createElement('a');link.href = url;link.download = `AI基金报告_${data?.title || '未命名'}_${data?.date || ''}.pdf`;document.body.appendChild(link);link.click();document.body.removeChild(link);URL.revokeObjectURL(url);message.success({ content: 'PDF导出成功', key: 'export' });return;}// 计算当前页的高度let currentPageHeight;if (leftHeight > a4HeightInCanvas) {// 需要寻找合适的分页点let cutPoint = position + a4HeightInCanvas;let isFound = false;// 向上搜索连续的空白行作为分页点let checkCount = 0;for (let y = position + a4HeightInCanvas; y >= position; y--) {let isBlankLine = true;// 检查这一行的像素是否全为白色for (let x = 0; x < canvas.width; x += 10) {// 每10个像素采样一次提高性能const pixelData = canvas?.getContext('2d')?.getImageData(x, y, 1, 1).data;// 检查像素是否接近白色(允许一些误差)if (pixelData?.[0] < 250 ||pixelData?.[1] < 250 ||pixelData?.[2] < 250) {isBlankLine = false;break;}}if (isBlankLine) {checkCount++;// 找到连续10行空白,确定为分页点if (checkCount >= 10) {cutPoint = y;isFound = true;break;}} else {checkCount = 0;}}// 如果没找到合适的分页点,就使用默认值currentPageHeight = isFound? Math.round(cutPoint - position): Math.min(leftHeight, a4HeightInCanvas);// 确保高度不为0if (currentPageHeight <= 0) {currentPageHeight = a4HeightInCanvas;}} else {// 最后一页,直接使用剩余高度currentPageHeight = leftHeight;}// 设置临时canvas的尺寸tempCanvas.width = canvas.width;tempCanvas.height = currentPageHeight;// 将原canvas对应部分绘制到临时canvasctx?.drawImage(canvas,0,position,canvas.width,currentPageHeight,0,0,canvas.width,currentPageHeight,);// 从第二页开始添加新页面if (position > 0) {pdf.addPage();}// 将当前页添加到PDFpdf.addImage(tempCanvas.toDataURL('image/jpeg', 1.0),'JPEG',0,0,a4Width,(a4Width / tempCanvas.width) * currentPageHeight,);// 更新剩余高度和位置leftHeight -= currentPageHeight;position += currentPageHeight;// 处理下一页setTimeout(processNextPage, 100);};// 开始处理页面processNextPage();} catch {message.error({ content: '导出PDF失败,请稍后重试', key: 'export' });}};return (<Spin spinning={loading} wrapperClassName={styles.spinWrapper}><div className={styles.exportBtn}><Button type="primary" onClick={handleExport}>导出PDF</Button></div><div className={styles.container} id="AI-REPORT-CONTAINER">这里为需要导出的页面内容,table,echart等</div></Spin>);
}

相关文章:

  • AI规则引擎:解锁SQL数据分析新姿势
  • RBTree的模拟实现
  • 《P2345 [USACO04OPEN] MooFest G》
  • PNG转ico图标(支持圆角矩形/方形+透明背景)Python脚本 - 随笔
  • STM32F103C8T6板子使用说明
  • Android架构 之 自定义native进程
  • loki grafana 页面查看 loki 日志偶发 too many outstanding requests
  • C语言之旅5---分支与循环【2】
  • 数睿通2.0数据中台,已购买源代码
  • 【docker】--镜像管理
  • 关于cleanRL Q-learning
  • ElasticSearch深入解析(十一):分页和分批统计的三种实现
  • 英语学习5.13
  • Lin4neuro 系统详解
  • FHQ平衡树
  • 什么是Git?
  • 计算机组成与体系结构:组相联映射(Set-Associative Mapping)
  • NY164NY165美光固态闪存NY166NY172
  • 学习日志05 java
  • MySQL数据库——视图
  • 西安市未央区委书记刘国荣已任西咸新区党工委书记
  • 筑牢安全防线、提升应急避难能力水平,5项国家标准发布
  • 男子发寻母视频被警方批评教育,律师:发寻亲信息是正当行为
  • 区域国别学视域下的东亚文化交涉
  • 历史地理学者成一农重回母校北京大学,担任历史系教授
  • “犍陀罗艺术与亚洲文明”在浙大对外展出