【发布时间】:2014-11-13 11:50:46
【问题描述】:
是否可以在 jsPDF 中包含自定义字体?
使用基本库,如果我在控制台登录“doc.getFontList()”,我会得到:
Courier, Helvetica, 时代, 快递, helvetica, 时代
但是,假设我想使用“Comic Sans”(不是我会;o))可以做到吗?
更好的是,我可以使用本地存储并已在站点中使用@font-face 声明的字体吗?
【问题讨论】:
标签: jspdf
是否可以在 jsPDF 中包含自定义字体?
使用基本库,如果我在控制台登录“doc.getFontList()”,我会得到:
Courier, Helvetica, 时代, 快递, helvetica, 时代
但是,假设我想使用“Comic Sans”(不是我会;o))可以做到吗?
更好的是,我可以使用本地存储并已在站点中使用@font-face 声明的字体吗?
【问题讨论】:
标签: jspdf
我发现这可以通过修改 jsPDF.js 以在公共 API 中公开现有的 addFont 方法来实现。
在jsPDF.js,查找:
//---------------------------------------
// Public API
添加以下内容:
API.addFont = function(postScriptName, fontName, fontStyle) {
addFont(postScriptName, fontName, fontStyle, 'StandardEncoding');
};
为了清晰起见,我将此方法放在其他字体方法附近 - API.setFont、API.setFontSize、API.setFontType 等。
现在在您的代码中,使用:
doc.addFont('ComicSansMS', 'Comic Sans', 'normal');
doc.setFont('Comic Sans');
doc.text(50,50,'Hello World');
这适用于我在加载 jsPDF 之前包含在 css 中的 @font-face 字体以及系统字体。使用 jsPDF 的插件框架可能有更好的方法来做到这一点,但这个快速而肮脏的解决方案至少应该让你继续前进。
请注意,doc.getFontList() 将不显示添加的字体:
// TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
【讨论】:
使用最新版本的jsPDF (1.5.3) 似乎要容易得多:
如果您查看文件夹jsPDF-master > fontconverter,则有一个文件fontconverter.html。在浏览器中打开并使用Browse... 按钮导航到并选择您的.ttf 字体文件。
点击“创建”。
该页面将提供要保存的“下载”。这将生成一个名为 [类似] RopaSans-Regular-normal.js 的 .js 文件。这需要包含在生成 PDF 的页面中。就个人而言,我已经在主页的标题中完成了它(请注意scripts的顺序):
<!-- pdf creation -->
<script src="FileSaver.js-master/src/FileSaver.js"></script>
<script src="jsPDF-master/dist/jspdf.debug.js"></script>
<!-- custom font definition -->
<script src="path-to-the-file-just-saved/RopaSans-Regular-normal.js" type="module"></script>
现在在你的 js 中的 PDF 生成方法中:
doc.setFont('RopaSans-Regular');
doc.setFontType('normal');
【讨论】:
这是我正在使用的解决方案...
首先,正如其他人所提到的 - 您需要这两个库:
下一步 - 第二个库要求您在名为 default_vfs.js 的文件中为其提供至少一种自定义字体。我正在使用 两个 自定义字体 - Arimo-Regular.ttf 和 Arimo-Bold.ttf - 都来自 Google Fonts。所以,我的default_vfs.js 文件看起来像这样:
(
(function (jsPDFAPI) {
"use strict";
jsPDFAPI.addFileToVFS('Arimo-Regular.ttf','[Base64-encoded string of your font]');
jsPDFAPI.addFileToVFS('Arimo-Bold.ttf','[Base64-encoded string of your font]');
})(jsPDF.API);
显然,您的版本看起来会有所不同,具体取决于您使用的字体。
有很多方法可以为您的字体获取 Base64 编码的字符串,但我使用的是:https://www.giftofspeed.com/base64-encoder/。
它允许您上传字体 .ttf 文件,它会为您提供 Base64 字符串,您可以将其粘贴到 default_vfs.js。
您可以在此处使用我的字体查看实际文件的外观:https://cdn.rawgit.com/stuehler/jsPDF-CustomFonts-support/master/dist/default_vfs.js
因此,一旦您的字体存储在该文件中,您的 HTML 应该如下所示:
<script src="js/jspdf.min.js"></script>
<script src="js/jspdf.customfonts.min.js"></script>
<script src="js/default_vfs.js"></script>
最后,您的 JavaScript 代码如下所示:
const doc = new jsPDF({
unit: 'pt',
orientation: 'p',
lineHeight: 1.2
});
doc.addFont("Arimo-Regular.ttf", "Arimo", "normal");
doc.addFont("Arimo-Bold.ttf", "Arimo", "bold");
doc.setFont("Arimo");
doc.setFontType("normal");
doc.setFontSize(28);
doc.text("Hello, World!", 100, 100);
doc.setFontType("bold");
doc.text("Hello, BOLD World!", 100, 150);
doc.save("customFonts.pdf");
这对大多数人来说可能是显而易见的,但是在那个addFont() 方法中,三个参数是:
addFileToVFS() 文件中的addFileToVFS() 函数中使用的字体名称setFont() 函数中使用的字体名称setFontType() 函数中使用的字体样式你可以在这里看到这个工作:https://codepen.io/stuehler/pen/pZMdKo
希望这对你和我一样有效。
【讨论】:
我正在使用 Angular 8,Todd's answer 为我工作。
从 fontconverter.html 获取 .js 文件后,您可以将其导入到 typescript 中,如下所示:
import fontref = require('path/to/font/CustomFont-normal.js')
那么加载字体所需要做的就是“调用”fontref:
makePdf() {
let doc = new jsPDF();
fontref; // 'call' .js to load font
doc.getFontList(); // contains a key-value pair for CustomFont
doc.setFont("CustomFont"); // set font
doc.setFontType("normal");
doc.setFontSize(28);
doc.text("Hello", 20, 20);
window.open(doc.output('bloburl')); // open pdf in new tab
}
【讨论】:
查看 fontconverter.html 后,发现它只是将 TTF 文件打包到 JS 文件中的 base64 字符串中,我想出了在创建文档之前调用的以下方法。它基本上完成了由 fontconverter.html 生成的各个文件所做的事情,只是按需:
async function loadFont(src, name, style, weight) {
const fontBytes = await fetch(src).then(res => res.arrayBuffer());
var filename = src.split('\\').pop().split('/').pop();
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(fontBytes)));
var callAddFont = function () {
this.addFileToVFS(filename, base64String);
this.addFont(filename, name, style, weight );
};
jsPDF.API.events.push(['addFonts', callAddFont]);
}
这样称呼它:
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-italic.ttf", "Exo-2", "italic", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-regular.ttf", "Exo-2", "normal", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500.ttf", "Exo-2", "normal", 500);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500italic.ttf", "Exo-2", "italic", 500);
它从 URL 加载字体,并将其添加到 VFS 和字体管理器。重要提示:字体名称不能包含空格。您不会收到任何警告,但生成的 PDF 要么无法打开,要么文本看起来很有趣。
【讨论】:
其中一些答案已经过时,因此我将 Rio 先生本人的自述文件链接到这篇文章的最新版本。下面是该自述文件中段落的副本,后面是自述文件本身的链接。希望这个额外的资源对您有所帮助:
使用 UTF-8 / TTF: PDF 中的 14 种标准字体仅限于 ASCII 码页。如果你想使用 UTF-8,你必须集成一个 自定义字体,提供所需的字形。 jsPDF 支持 .ttf 文件。所以如果你想在你的 pdf,你的字体必须有必要的中文字形。所以检查是否 您的字体支持所需的字形,否则它将显示空白 空格而不是文本。
要将字体添加到 jsPDF,请使用我们的 fontconverter /fontconverter/fontconverter.html 。 fontconverter 将创建一个 js 文件,其中提供的 ttf 文件的内容为 base64 编码 jsPDF 的字符串和附加代码。你只需要添加这个 为您的项目生成 js 文件。然后你就可以开始使用了 在您的代码中设置字体方法并编写您的 UTF-8 编码文本。
https://github.com/MrRio/jsPDF/blob/master/README.md#use-of-utf-8--ttf
【讨论】:
到目前为止,我发现的最简单的方法是使用 jspdf-customfonts 包。
只需通过以下方式安装软件包
npm i jspdf-customfonts
然后在 index.html 的 head 标签中添加以下文件以进行默认配置
script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>
<script src="dist/jspdf.customfonts.min.js"></script>
<script src="dist/default_vfs.js"></script>
现在您可以下载您想要的任何字体的 ttf 文件。然后去this站点,选择你的字体并复制代码,你就完成了!
【讨论】: