我在 Angular 应用程序中使用 Highcharts,并且我已使用以下 CSS 代码成功更改了轴标签的字体系列:
.highcharts-yaxis-labels、.highcharts-xaxis-labels、.highcharts-root、.mat-form-field { 字体系列:“YekanBakh”!重要; }
在浏览器中显示图表时,这非常有效。但是,当我尝试使用 html2pdf 库生成 PDF 时,自定义字体系列未应用于生成的 PDF 中。
这是我用来生成 PDF 的代码:
public onPrint(): void { const content = document.getElementById('print-layout'); const options = { margin: [5, 2, 5, 2], filename: 'document.pdf', pagebreak: { mode: ['avoid-all', 'css'], before: "#nextpage" }, image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2 }, jsPDF: { unit: 'mm', orientation: 'p', format: 'a4', putOnlyUsedFonts: true, compress: true, floatPrecision: 'smart' }, }; html2pdf() .from(content) .set(options) .save(); }
将图表打印为 PDF 时,不会应用 Highcharts 标签的 YekanBakh 字体。相反,尽管 CSS 在浏览器中正确应用,但它默认为其他字体。
我的问题: 如何确保自定义字体(“YekanBakh”)应用于 html2pdf 生成的 PDF 中的轴标签?
Verified that the font is properly applied in the browser.
Added !important to the CSS rule to ensure it's being applied.
Ensured that Highcharts rendering works well on the screen, but the issue persists in the PDF output.
我自己找到了答案
该问题与 Highcharts 本身没有直接关系,而是与生成 PDF 时如何在 SVG 元素中处理字体有关。 Highcharts 图表呈现为 SVG,而 html2pdf 不会自动在这些 SVG 中嵌入自定义字体。这就是为什么自定义“YekanBakh”字体没有出现在 PDF 中,尽管它在浏览器中运行良好。
为了确保在 PDF 中应用自定义字体,您需要在生成 PDF 之前将字体注入到元素中。这样,字体就会嵌入到 SVG 中,并且在将 HTML 内容转换为 PDF 时会保留该字体。
解决问题的方法如下:
从 DOM 中提取所有 SVG 元素。 使用 和 动态地将 @font-face 规则插入到每个 SVG 中。 将字体注入 SVG 后生成 PDF。
const content: any = document.getElementById('print-layout');
// Step 1: Find all SVG elements in the print-layout
const svgs = content?.querySelectorAll('svg');
// Step 2: Define the font-face to be embedded in SVG
const fontFace = `
@font-face {
font-family: 'YekanBakh';
src: url(data:application/font-woff;charset=utf-8;base64,AAEAAAAPAIAAAwBwRFNJRwAAAAEAANI8AAAACEdERUYKqwqtAADSRAAA) format('woff');
}
`;
// Step 3: Loop through each SVG and inject the font-face style
svgs?.forEach((svg: any) => {
const defs = svg.querySelector('defs') || document.createElement('defs');
let styleElement = svg.querySelector('style');
// If <style> tag doesn't exist, create one and append to defs
if (!styleElement) {
styleElement = document.createElement('style');
defs.appendChild(styleElement);
}
// Inject the font-face rule into the style tag
styleElement.innerHTML = fontFace;
// Append defs to the SVG if it's not already present
if (!svg.querySelector('defs')) {
svg.appendChild(defs);
}
});