使用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
相关产品推荐
相关产品推荐

