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; // 调整下一页图片的起始位置
  }
}
相关推荐
用户1880687493521 分钟前
戴着 Rokid 接成语:用 AIUI 做一局有提示、有复盘的“接着说”
前端
Sakura_j_h_11 分钟前
Three.js 单文件离线机械臂工作台:爆炸图、透明外壳与剖面
前端·机械臂·webgl·three.js·1024程序员节·esbuild
计算机魔术师2 小时前
管谷歌的不是Pichai一个人,是一整层AI智能体
前端
米米商聊2 小时前
图标能点,按钮就可用了吗?键盘、名称与收藏状态
前端·javascript
Younglina2 小时前
三个晚上,我和 WorkBuddy 做了个生图网站
前端·后端·ai编程
xy34532 小时前
Axure 9.0 内联框架加载方式
前端·ui·html·axure·原型·产品设计
技术小甜甜3 小时前
【Cursor】Skill 被标黄色警告,怎么改成合格的 SKILL.md
开发语言·javascript·ai编程·cursor·1024程序员节·ai agent·skills
陈随易4 小时前
副业搞钱点子之收入查看器
前端·后端
Profile排查笔记4 小时前
浏览器指纹逆向怎么分析:从网络请求追踪到 JavaScript 采集链
前端·人工智能·后端·自动化
hudie7654 小时前
LikeShop 二开最常改的 5 个文件(附改前改后对比)
前端·uni-app·php·个人开发