PDF 下载弹窗 content 区域可行性方案

需求:按钮点击下载弹窗 content 内容为 PDF

实现方案:

  • 获取弹窗 content 的 DOM 元素:通过ref获取需要截图的内容区域。

  • 将 DOM 转换为图片:使用 html2canvas 库将 DOM元素渲染为 Canvas ,在转换为图片。

  • 将图片生成PDF:使用 jspdf 库创建 PDF 文档,将图片添加到 PDF 中。

  • 触发 PDF 下载:通过 jspdf 的 API 生成 PDF 文件并触发浏览器下载。

1.安装依赖

复制代码
npm install html2canvas jspdf --save

2.组件实现

核心是给弹窗的 content 区域添加和 ref,并绑定下载按钮的点击事件:

复制代码
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

// 逻辑部分
// 创建ref用于获取content区域的DOM
const contentRef = useRef(null);

// 下载PDF的核心函数
const downloadAsPDF = async () => {
    // 1. 检查content区域是否存在
    if (!contentRef.current) return;
    try {
      // 2. 使用html2canvas将DOM转为Canvas
      const canvas = await html2canvas(contentRef.current, {
        useCORS: true, // 解决跨域图片问题
        scale: 2, // 缩放比例,提高清晰度(默认1,2表示2倍分辨率)
        logging: false // 关闭控制台日志});
        // 3. 将Canvas转为图片数据
        const imgData = canvas.toDataURL('image/png');
        // 4. 创建PDF文档(A4尺寸,纵向)
        const pdf = new jsPDF('p', 'mm', 'a4');
        // 获取A4纸的尺寸(单位:mm)
        const a4Width = 210; 
        const a4Height = 297;
        // 获取图片的实际尺寸(单位:px)
        const imgWidth = canvas.width; 
        const imgHeight = canvas.height;
        // 计算图片在PDF中的缩放比例(保持宽高比,适应A4宽度)
        const scale = a4Width / imgWidth; 
        const pdfImgHeight = imgHeight * scale;
        // 5. 将图片添加到PDF(x=0, y=0,宽度为A4宽度,高度按比例计算)
        pdf.addImage(imgData, 'PNG', 0, 0, a4Width, pdfImgHeight);
        // 6. 触发下载(文件名自定义)
        pdf.save('弹窗内容.pdf');
      } catch (error) {
        console.error('下载PDF失败:', error);
      }
    };
// DOM部分
return (
    <>
    <Modal
        title="查看AI评估"
        open={aiResumeModalOpen}
        footer={null}
        centered
        onCancel={handleCancel}
        width={1000}
        classNames={{
          content: styles.myContent,
          header: styles.filterHeader,
          body: styles.filterBody,
        }}
        footer={
            <Button onClick={downloadAsPDF}>
                PDF下载
            </Button>
        }
      >
          <div ref={contentRef}>
            <Flex vertical gap={30} className={styles.filterBody}>
              <ApplyPeopleHead applyDetail={selectApplyDetail} />
              <ApplyPeopleAiResume selectApplyDetail={selectApplyDetail} />
            </Flex>
          </div>
      </Modal>
    </>
)

3.分页处理(可选)

如果 content 内容超过一页 A4 纸,可通过计算高度分割图片为多页:

复制代码
// 在添加图片时判断是否需要分页
const totalPages = Math.ceil(pdfImgHeight / a4Height); // 计算总页数
let yPosition = 0; // 当前页的Y轴起始位置

for (let i = 0; i < totalPages; i++) {
  pdf.addImage(imgData, 'PNG', 0, yPosition, a4Width, pdfImgHeight);
  if (i < totalPages - 1) {
    pdf.addPage(); // 新增一页
    yPosition = -a4Height * i; // 调整下一页图片的起始位置
  }
}
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端