如何在 dataTables PDF 导出中正确呈现字形?

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

我正在使用

dataTables
来呈现游泳队的最佳时间表。适用宇宙中有两个级别的资格时间,我用 unicode 星形符号在表中注释时间。 B 级 为轮廓,A 级 为实线。分别是
U+2606
U+2605
。浏览器视图符合预期:

dataTables view of best times table

但是,当我导出为 PDF 时,字形不会呈现。

PDF export of dataTables view of best times

我读到的内容表明,这是一个问题,因为

Roboto
中的默认字体
pdfMake
不支持字形,并且要包含其他字体,我必须编辑
vfs_fonts.js
文件并包括我想要包括的字体的 base-64 编码定义。这提出了自己的挑战,因为您需要给定字体的重新分发许可证。我发现很难确认给定的字体是否具有我需要的字形,并且我尝试使用我发现的免费字体产生了奇怪的错误。

$.ajax({
    url: '/ttf/FreeSans-LrmZ.ttf' ,
    success: function(result) {
        window.pdfMake.vfs["FreeSans.ttf"] = btoa(unescape(encodeURIComponent(result))) ;
    }
});

....

customize: function (doc) {
    pdfMake.fonts = {
        Roboto: {
            normal: 'Roboto-Regular.ttf',
            bold: 'Roboto-Medium.ttf',
            italics: 'Roboto-Italic.ttf',
            bolditalics: 'Roboto-MediumItalic.ttf'
        },
        freeSans: {
            normal: 'FreeSans.ttf',
        }
    };
    doc.defaultStyle.font = "freeSans";

....

embedded.js:15  Uncaught (in promise) TypeError: Cannot read properties of null (reading 'advanceWidth')

我想我确实有两个问题:1)我如何找到合适的字体来正确呈现我需要的两个unicode字符? 2) 我如何正确合并它,以便解决我的

js
错误并成功导出正确渲染的 PDF?

我参考了以下问题,但无法解决我的问题:

无法在 PDFMAKE 中使用特殊字符/字形,即使导入的字体包含这些字符/字形

pdfmake - 使用自己的字体不起作用

数据表和 PDFmake

javascript datatables pdfmake
1个回答
0
投票

我建议您一次只问一个具体问题。我认为你的两个问题很不同。

话虽如此,以下是一些部分答案:


1) 如何找到合适的字体来正确呈现我需要的两个 unicode 字符?

这是 Stack Overflow 的题外话 - 这不是一个编程问题。

另外,无论如何,我没有一个好的(偏离主题!)的答案给你。我在快速搜索中找到的所有“免费商业用途”可下载字体都不包含

符号。

这也包括您在问题中尝试使用的字体。尽管它是“免费”和“arial”,但它仍然具有一组有限的 Unicode 字符、符号和字形。不包括 Unicode Miscellaneous Symbols 块。

您可以使用这个免费供个人使用字体 - 但这显然不适合商业用途。

不过,它确实包括星星:

enter image description here


2)我如何正确合并它,以便解决我的js错误并成功导出正确渲染的PDF?

您问题中的JavaScript代码无法正确处理下载的二进制字体文件数据,导致无效的base-64字符串。

jQuery 没有直接的内置方法来处理二进制文件,尽管您可以在 Stack Overflow 中搜索一些方法。

在这种情况下,我发现使用纯 JavaScript 更简单,而不是 jQuery 的

ajax

具体来说,以下使用

FleReader.readAsDataUrl
,因为使用这种方法时:

result
属性包含...文件的数据作为base64编码的字符串。

这就是我们想要的!

var req = new XMLHttpRequest();
req.open("GET", fontUrl, true);
req.responseType = "blob";
req.onload = function (event) {
  const blob = req.response;
         
  var reader = new FileReader();
  reader.readAsDataURL(blob); 
  reader.onloadend = function() {
    const base64data = reader.result.replace(/^data:.+;base64,/, '');            
  }
}

上面的代码基于类似问题的这个答案


但是,这仍然无法解决 PDF 字体问题,因为(如上所述)您使用的特定字体不包含您需要的字形。

但尽管如此,这里是完整的 DataTables 代码,您可以自己复制并运行。

(这是使用最新版本的 DataTables (2.0.0),带有新引入的

layout
选项。您可能使用的是旧版本,没有该选项 - 但这对于 特定 基础并不重要您面临的 64 个问题可以使用旧的 DataTables
dom
选项(如果您愿意)。)

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Demo</title>

  <link href="https://cdn.datatables.net/2.0.5/css/dataTables.dataTables.css" rel="stylesheet">
  <link href="https://cdn.datatables.net/buttons/3.0.2/css/buttons.dataTables.css" rel="stylesheet">
 
  <script src="https://code.jquery.com/jquery-3.7.0.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
  <script src="https://cdn.datatables.net/2.0.5/js/dataTables.js"></script>
  <script src="https://cdn.datatables.net/buttons/3.0.2/js/dataTables.buttons.js"></script>
  <script src="https://cdn.datatables.net/buttons/3.0.2/js/buttons.html5.js"></script>

  <link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">  
  
</head>

<body>

<div style="margin: 20px;">

    <table id="example" class="display dataTable cell-border" style="width:100%">
        <thead>
            <tr>
                <th>Name</th>
                <th>Position</th>
                <th>Office in Country</th>
                <th>Age</th>
                <th>Start date</th>
                <th>Salary</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Tiger Nixon</td>
                <td>System Architect</td>
                <td>Edinburgh</td>
                <td>61 ☆</td>
                <td>2011/04/25</td>
                <td>$320,800</td>
            </tr>
            <tr>
                <td>Garrett Winters</td>
                <td>Accountant</td>
                <td>Tokyo</td>
                <td>63 ★</td>
                <td>2011/07/25</td>
                <td>$170,750</td>
            </tr>
            <tr>
                <td>Ashton Cox</td>
                <td>Junior "Technical" Author</td>
                <td>San Francisco</td>
                <td>66</td>
                <td>2009/01/12</td>
                <td>$86,000</td>
            </tr>
        </tbody>
    </table>

</div>

<script>

$(document).ready(function() {

  $('#example').DataTable({
    layout: {
      topStart: {
        buttons: [{
          extend: 'pdfHtml5',
          customize: function ( doc ) {
            processDoc( doc );
          }
        }]
      }
    }
  });

} );

  function processDoc( doc ) {
  
    const fontUrl = 'https://static.miraheze.org/argobdpwiki/5/5d/FreeSans-LrmZ.ttf';
    
    var req = new XMLHttpRequest();
    req.open("GET", fontUrl, true);
    req.responseType = "blob";
    req.onload = function (event) {
      const blob = req.response;
         
      var reader = new FileReader();
      reader.readAsDataURL(blob); 
      reader.onloadend = function() {
        const base64data = reader.result.replace(/^data:.+;base64,/, '');            
        pdfMake.vfs["FreeSans.ttf"] = base64data;
        pdfMake.fonts = {
          Roboto: {
            normal: 'Roboto-Regular.ttf',
            bold: 'Roboto-Medium.ttf',
            italics: 'Roboto-Italic.ttf',
            bolditalics: 'Roboto-MediumItalic.ttf'
          },
          FreeSans: {
            normal: 'FreeSans.ttf',
            bold: 'FreeSans.ttf',
            italics: 'FreeSans.ttf',
            bolditalics: 'FreeSans.ttf'
          }
        };
        // modify the PDF to use a different default font:
        doc.defaultStyle.font = "FreeSans";
      }
    };

    req.send();
    
  }

</script>

</body>
</html>

你可以在上面的代码中看到我使用的URL:

const fontUrl = 'https://static.miraheze.org/argobdpwiki/5/5d/FreeSans-LrmZ.ttf';

如果您找到包含所需字形且具有合适许可证的字体文件,您可以将我的演示 URL 更改为您想要使用的 URL。

(显然,您可以自己托管相关的字体文件 - 它不必是外部 URL,就像我的示例一样。它可以是特定于您的应用程序的 URL。)

© www.soinside.com 2019 - 2024. All rights reserved.