You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jsPDF将HTML转PDF时自定义字体未生效问题求助

解决jsPDF转换HTML时自定义字体不生效的问题

问题根源:浏览器能正常解析HTML里@font-face定义的Base64字体,但html2canvas生成画布时可能未等待字体完全加载,或是jsPDF的html方法无法自动提取HTML中的字体定义,导致PDF用了回退字体。

以下是针对性的解决步骤和修改后的代码:


1. 确保字体完全加载后再生成PDF

用FontFaceAPI显式加载字体,等所有自定义字体加载完成后再执行转换逻辑,避免html2canvas捕获未渲染完成的内容。

2. 手动给jsPDF注册自定义字体

HTML里的@font-face不能直接被jsPDF识别,需要手动把Base64字体注册到jsPDF的虚拟文件系统(VFS)中,再添加为可用字体。

3. 调整html2canvas配置

提高缩放比例保证PDF清晰度,同时允许加载本地Base64资源。


修改后的完整代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Custom Font PDF</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    <style>
      @font-face {
        font-family: 'Noto Serif Bold';
        src: url('data:font/woff2;charset=utf-8;base64,d09xxaxadfdfdfdfGMg...cAAA==') format('woff2');
        font-weight: bold;
      }

      @font-face {
        font-family: 'Noto Serif';
        src: url('data:application/octet-stream;base64,AAEAAAANAIAAAwBQ..AA=') format('truetype');
        font-weight: normal;
      }

      .custom-font-bold {
        font-family: 'Noto Serif Bold';
        font-size: 20px;
        color: #333333;
      }

      .custom-font-regular {
        font-family: 'Noto Serif';
        font-size: 16px;
        color: #555555;
      }
    </style>
  </head>
  <body>
    <button onclick="convertToPDF()">Generate PDF</button>
    <div id="contentToPrint">
      <p class="custom-font-bold">This is using the Bold Custom Font</p>
      <p class="custom-font-regular">This is using the Regular Custom Font</p>
    </div>

    <script>
      const { jsPDF } = window.jspdf;

      // 给jsPDF注册自定义字体
      function registerFonts(doc) {
        // 粗体字体纯Base64(去掉data:前缀)
        const boldFontBase64 = 'd09xxaxadfdfdfdfGMg...cAAA==';
        // 常规字体纯Base64
        const regularFontBase64 = 'AAEAAAANAIAAAwBQ..AA=';

        // 添加到虚拟文件系统
        doc.addFileToVFS('NotoSerif-Bold.woff2', boldFontBase64);
        // 注册字体:文件名、字体名、字重
        doc.addFont('NotoSerif-Bold.woff2', 'Noto Serif Bold', 'bold');

        doc.addFileToVFS('NotoSerif-Regular.ttf', regularFontBase64);
        doc.addFont('NotoSerif-Regular.ttf', 'Noto Serif', 'normal');
      }

      // 等待所有自定义字体加载完成
      async function loadFonts() {
        const boldFont = new FontFace(
          'Noto Serif Bold',
          'url(data:font/woff2;charset=utf-8;base64,d09xxaxadfdfdfdfGMg...cAAA==)'
        );
        const regularFont = new FontFace(
          'Noto Serif',
          'url(data:application/octet-stream;base64,AAEAAAANAIAAAwBQ..AA=)'
        );
        
        // 并行加载字体
        await Promise.all([boldFont.load(), regularFont.load()]);
        // 添加到文档字体集
        document.fonts.add(boldFont);
        document.fonts.add(regularFont);
      }

      async function convertToPDF() {
        // 先等字体加载完
        await loadFonts();
        
        const doc = new jsPDF();
        // 注册字体到当前PDF实例
        registerFonts(doc);

        const elementHTML = document.querySelector("#contentToPrint");

        doc.html(elementHTML, {
          callback: (doc) => doc.save("custom-font.pdf"),
          margin: [10, 10, 10, 10],
          html2canvas: {
            scale: 2, // 提高缩放比例避免PDF模糊
            useCORS: false, // 允许加载Base64资源
          },
          x: 10,
          y: 10,
        });
      }
    </script>
  </body>
</html>

关键细节说明

  • 简化字体名:去掉原字体名中的LSTCNP+前缀,避免特殊字符导致jsPDF或html2canvas识别失败。
  • FontFace加载:确保字体完全加载后再执行转换,防止html2canvas用回退字体渲染。
  • jsPDF字体注册:addFileToVFS需要纯Base64字符串(不要带data:...前缀),addFont要和CSS里的字体名、字重对应。
  • html2canvas缩放:scale设为2或更高,生成的PDF清晰度更好,避免模糊。

内容的提问来源于stack exchange,提问作者Krunal Lathia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:17:02