返回

如何导出带有自定义字体的D3图表?

vue.js

如何使用 html2canvas 导出带有自定义字体的 D3 图表?

你是否遇到过使用 html2canvas 将精心制作的 D3 图表导出成图片时,却发现图表上的自定义字体无法正常显示的窘境?你或许尝试过求助于 html-to-image,却迎面撞上了令人沮丧的 429 错误?别担心,本文将带领你抽丝剥茧,深入分析问题的根源,并提供一套行之有效的解决方案,助你生成完美无瑕的图表截图,其中包含你心仪的自定义字体。

追根溯源:探究字体加载背后的秘密

html2canvas 和 html-to-image 在将网页内容渲染成图片时,就像一位急于求成的画家,只顾着捕捉眼前的景象,却忽略了等待颜料完全干透。网页中使用的自定义字体通常需要从外部服务器加载,而 html2canvas 和 html-to-image 在渲染过程中,往往等不及这些字体文件完全加载完毕,便急匆匆地开始了“创作”,导致最终生成的图片中,自定义字体无法正常显示。

破译难题:确保字体加载先人一步

想要解决这个问题,我们需要像一位经验丰富的导演一样,确保所有演员(字体文件)在正式演出(渲染图表)之前就位。

1. @font-face:邀请自定义字体加入舞台

首先,我们需要使用 CSS 的 @font-face 规则将自定义字体引入到我们的项目中。这就像在剧本中添加角色一样,告诉浏览器我们将会使用哪些字体。你可以在 CSS 文件中添加 @font-face 规则,或者直接在 HTML 文件的 <style> 标签中编写。

@font-face {
  font-family: 'MyCustomFont';
  src: url('path/to/MyCustomFont.woff2') format('woff2'),
       url('path/to/MyCustomFont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

请记得将 path/to/MyCustomFont.woff2path/to/MyCustomFont.woff 替换为你的自定义字体文件的实际路径。

2. FontFace API: 确认演员是否准备就绪

JavaScript 提供了 FontFace API,我们可以用它来监测字体是否加载完成。就像一位尽职的舞台监督,在幕后确认演员是否已化好妆、穿好戏服。

const myCustomFont = new FontFace('MyCustomFont', 'url(path/to/MyCustomFont.woff2)');

myCustomFont.load().then((font) => {
  // 字体加载完成,可以开始导出图表
  document.fonts.add(font);

  // 执行 html2canvas 或 html-to-image 导出操作
});

在这段代码中,我们首先创建了一个新的 FontFace 对象,并将自定义字体的名称和文件路径传递给它。然后,我们调用 load() 方法来加载字体,并在加载完成后执行回调函数。在回调函数中,我们将加载完成的字体添加到 document.fonts 中,就像通知导演演员已就位,可以开始拍摄了。最后,我们就可以放心地执行 html2canvas 或 html-to-image 的导出操作了。

3. 优化 html2canvas 参数:为“拍摄”创造良好环境

为了进一步提高导出的成功率,我们可以对 html2canvas 的一些配置参数进行调整,就像为拍摄准备合适的灯光、布景一样。

  • useCORS: true: 允许 html2canvas 从跨域加载资源,例如从 CDN 加载的字体文件。
  • allowTaint: true: 允许 html2canvas 渲染被污染的画布,这在处理跨域图片时非常有用。
  • logging: true: 开启日志记录功能,方便我们排查问题,就像在拍摄现场放置监控设备一样。
html2canvas(document.getElementById('my-d3-chart'), {
  scale: 2, // 设置导出图片的缩放比例
  scrollY: -window.scrollY, // 修正滚动条位置
  backgroundColor: null, // 设置背景颜色为透明
  useCORS: true, 
  allowTaint: true, 
  logging: true,
}).then((canvas) => {
  // 将 canvas 转换成图片并下载
  const link = document.createElement('a');
  link.download = 'my-d3-chart.png';
  link.href = canvas.toDataURL('image/png');
  link.click();
});

大功告成:自定义字体完美呈现

通过以上步骤,我们就成功地解决了使用 html2canvas 或 html-to-image 导出 D3 图表时,自定义字体无法正常显示的难题。现在,你可以自信地将你的 D3 图表导出成图片,并与他人分享你的杰作了!

常见问题解答:

  1. 为什么我使用了 @font-face 引入字体,但导出图片时仍然无法正常显示?

    • 可能是因为字体文件路径错误,请仔细检查路径是否正确。
    • 也可能是因为字体文件格式不受支持,建议使用 WOFF2 或 WOFF 格式的字体文件。
  2. 如何检查字体是否加载完成?

    • 可以使用浏览器的开发者工具,在“Network”标签页中查看字体文件的加载状态。
    • 也可以在 JavaScript 代码中使用 FontFace API 来监测字体加载状态。
  3. 为什么 html2canvas 会出现 429 错误?

    • 429 错误表示请求过于频繁,可能是因为你短时间内执行了太多次导出操作。
    • 可以尝试降低导出频率,或者使用付费版本的 html2canvas 服务。
  4. 除了 html2canvas 和 html-to-image,还有其他方法可以导出 D3 图表吗?

    • 可以使用 D3.js 自带的 svg.node().parentNode.innerHTML 方法将 SVG 元素转换成字符串,然后复制到剪贴板或保存为 SVG 文件。
    • 也可以使用第三方库,例如 save-svg-as-png,将 SVG 元素转换成 PNG 图片。
  5. 如何优化 D3 图表的导出质量?

    • 可以尝试提高导出图片的缩放比例,例如将 scale 参数设置为 2 或更高。
    • 可以尝试设置背景颜色为透明,以避免导出图片时出现白色边框。