jsPDF PubSub 错误 – “没有用于字体的 unicode cmap”

问题描述 投票:0回答:5

我正在尝试向 jsPDF 添加自定义字体。我将文件转换为 base64 并执行了以下操作:

doc.addFileToVFS("font/rajdhani-regular-webfont.woff", base64enc);

其中base64enc是base 64编码的字符串

然后我添加字体如下:

doc.addFont('font/rajdhani-regular-webfont.woff', 'rajdhani', 'normal');

doc.setFont('rajdhani');

但是,我不断收到以下错误

[Error] jsPDF PubSub Error – "No unicode cmap for font" – Error: No unicode cmap for font — jspdf.min.js:9068
Error: No unicode cmap for font — jspdf.min.js:9068registerTTF — jspdf.min.js:9068i — jspdf.min.js:9027:86open — jspdf.min.js:9032(anonymous function) — jspdf.min.js:6031publish — jspdf.min.js:308yt — jspdf.min.js:729:166addFont — jspdf.min.js:1286callme — freport.php:500onclick — freport.php:100
    publish (jspdf.min.js:29:5989)
    yt (jspdf.min.js:29:18435)
    addFont (jspdf.min.js:29:33701)
    callme (freport.php:500)
    onclick (freport.php:100)

我不知道为什么会这样。

javascript html jspdf
5个回答
5
投票

我也一直在挣扎,但我终于找到了方法!

正如这里提到的,有一个由jsPDF贡献者制作的字体转换器,您可以在这里找到。

首先在此处上传您的字体,然后输入您的字体名称。它将生成 JS 文件,然后您需要将其包含在您的项目中。如果您愿意,这可以是您的 js 文件夹。

一旦它进入您的文件夹,请将此脚本标签添加到您的index.html(或您需要jsPDF的任何html文件)。

<script src="./fontName.js"></script>

现在您已经使用该文件将字体自动添加到 jsPDF Api 中,您可以继续操作并从代码中删除以下两行

doc.addFileToVFS("font/rajdhani-regular-webfont.woff", base64enc);
doc.addFont('font/rajdhani-regular-webfont.woff', 'rajdhani', 'normal');

完成此操作后,只需检查从转换器下载的文件,您应该在最底部看到您的字体名称位于以下代码的第二个参数

this.addFont('fontFile.woff', 'THIS IS FONT NAME' , '.......');

复制该名称。对于这个例子,我们可以说它是“rajdhani”。因此,您只需将其放在在 jsPDF (doc) 实例上创建的任何文本之前即可。

doc.setFont('rajdhani');

您可以简单地用下面的方法进行测试

/* 
"p" for portrait page orientation
"pt" for points. default is mm
"a4" is page size 
*/
var doc = new jsPDF("p","pt","a4"); 
doc.setFont('rajdhani');
doc.text('This is a test', 20,20);
doc.save('filename.pdf');

现在您应该会看到一个 pdf,其上边距为 20px,左 20px,并用您的字体样式写着“这是一个测试”。

希望这有帮助:)


1
投票

对于 ES6 模块用户来说,步骤也非常相似。

如果您像我一样在这里寻找 Ionic 4 Angular TypeScript 的解决方案,下面是对我有用的解决方案!

首先您需要通过 npm 安装软件包,如下所示。

npm install jspdf@latest --save

之后,正如我之前的回复中提到的,有一个由 jsPDF Contributers 制作的字体转换器,您可以在here找到它。使用它来上传您的字体文件并将其包含在您的项目中易于引用的 TS 文件中的某个位置,因此它可以与 ts 文件位于同一文件夹中。

-fontname-style.js // <<--- Here (This is the file you downloaded from converter)
-custom.page.module.ts
-custom.page.html
-custom.page.scss
-custom.page.spec.ts
-custom.page.ts

现在在您的 custom.page.ts 中导入以下内容;

import * as jsPDF from 'jspdf';
import './fontname-style.js';

//OPTIONAL (Only import if you want to use autotable)
import 'jspdf-autotable';
import { autoTable as AutoTable } from 'jspdf-autotable';

完成此操作后,只需检查从转换器下载的文件,您应该在最底部看到下面代码的第二个参数上的字体名称。

this.addFont('fontFile.ttf', 'fontName', '.......');

现在您可以在 custom.page.ts 中创建这样的函数;

//custom.component.ts or custom.page.ts etc.
exportPDF(){
  var doc = new jsPDF("p","pt","a4"); // You can set your own  paramaters
  doc.setFont('fontName');
  doc.text('This is a test', 20,20); // You can set your own margins
  return doc.save('filename.pdf');
}

现在您应该会看到一个 pdf,左上边距为 20px,上边距为 20px,并用您的字体样式写着“这是一个测试”:)

可选插件 - AutoTable for jsPDF

如果您想使用 jsPDF 的 autotable 插件,请从 npm 安装以下软件包。

npm install jspdf-autotable@latest --save

安装后,将这两个导入添加到您的custom.page.ts

import 'jspdf-autotable';
import { autoTable as AutoTable } from 'jspdf-autotable';

如果您愿意,您可以创建列和标题数据

在我们之前创建的exportPDF()函数中添加这些行;

//custom.component.ts or custom.page.ts etc.
exportPDF(){
  var doc = new jsPDF("p","pt","a4");
  doc.setFont('fontName');
  doc.text('This is a test', 20,20); // <-- Remove this line
  ((doc as any).autoTable as AutoTable)({
    head: [['Name', 'Email', 'Country']], // <-- Table headers
    body: [                               // <-- Table body
            ['David', '[email protected]', 'Sweden'],
            ['Castille', '[email protected]', 'Norway'],
            // ...
          ],
    styles: { font: "fontName" } /* <-- This is for the font to work in your 
  table */
  });

  return doc.save('filename.pdf');
}

现在您应该获得一个 pdf 文件,其中包含使用您的字体的表格:)

我希望这对某人有帮助。


0
投票

我遇到了同样的问题,并按照@TuncGerdan 解释的步骤进行操作。我的错误已清除,但我在控制台中收到以下警告。

jspdf.min.js:29 Unable to look up font label for font 'font name', 'normal'. Refer to getFontList() for available fonts.

当我使用 doc.getFontList() 获取字体列表时,我可以看到列表中包含的自定义字体。

有人可以帮忙吗。


0
投票

当我尝试以二进制形式添加新字体而没有像

docs
中提到的转换器时,我也得到了Error: No unicode cmap for font。我认为他们的例子中的关键是:

const myFont = ... // load the *.ttf font file as binary string

对我来说,不清楚

binary string
的含义。然而,查看他们的转换器可以清楚地看出
binary string
应该是一个 base64 编码的字符串。

所以对我来说,从远程获取字体并添加它可以使用以下方法:

/**
 * load a font from remote and add it to jsPDF doc
 * @param path the path of the font, e.g. '/app/fonts/My-Font.ttf'
 * @param doc the jsPDF doc instance to install the font to
 * @return {Promise<void>}
 */
async function loadFont(path, doc) {
    let response = await fetch(path).catch((e) => console.error(e));
    if (!response) {
        return;
    }
    let fontName = path.substring(path.lastIndexOf("/") + 1);
    console.log("using font", fontName);
    let contentBuffer = await response.arrayBuffer();
    let contentString = util.arrayBufferToBase64(contentBuffer)
    if (contentString) {
        doc.addFileToVFS(fontName, contentString);
        doc.addFont(fontName, fontName, "normal");
        doc.setFont(fontName);
    }
}

对于

util.arrayBufferToBase64
我正在使用这个Stackoverflow答案中的函数。


0
投票

我遇到了一个重要问题!不支持 WOFF 和 OTT(坚持使用 ttf)。我在这方面浪费了太多时间,这个功能应该是标准的。事实上,他们有一个狡猾的转换器网站而不是内置功能,这一事实令人难以置信(也没有提到文件类型限制,在他们的应用程序上进行了简单的扩展检查),类似于@klues,但使用文件阅读器来简化,这里是我的角度功能

  this.loadFont('VIC-med', 'assets/Fonts/VIC-Medium.ttf');
  

  loadFont(fontName: string, filePath: string, weight: 'normal'| 'bold' | 'italic'| 'bolditalic' = 'normal') {
    this.http.get(filePath, { responseType: 'blob' })
      .subscribe({
        next: (blob: Blob) => {
          const fileName =  filePath.substring(filePath.lastIndexOf("/") + 1);
          const reader = new FileReader();
          reader.onloadend = () => {
            const file64 = (reader.result as string).split(',')[1];

            this.pdf.addFileToVFS(fileName, atob(file64));
            this.pdf.addFont(fileName, fontName, weight);
          };
          reader.readAsDataURL(blob);
        },
        error: (error) => {
          console.error('Error loading font:', error);
        }
      });
  }

对于 ES 来说也是如此

loadFont(fontName: string, filePath: string, weight: 'normal'| 'bold' | 'italic'| 'bolditalic' = 'normal') {
    fetch(filePath)
      .then(response => response.blob())
      .then(blob => {
        const fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
        const reader = new FileReader();
        reader.onloadend = () => {
          const file64 = (reader.result as string).split(',')[1];

          this.pdf.addFileToVFS(fileName, atob(file64));
          this.pdf.addFont(fileName, fontName, weight);
        };
        reader.readAsDataURL(blob);
      })
      .catch(error => {
        console.error('Error loading font:', error);
      });
}
© www.soinside.com 2019 - 2024. All rights reserved.