如何用html2canvas导出带正确Poppins字体的D3图表为PNG?
解决Vue3+D3图表导出PNG时Poppins字体不显示的问题
核心原因
html2canvas无法正确加载远程CDN字体,或字体未在渲染完成前加载完毕;html-to-image因频繁请求CDN字体触发429限流。
解决方案
1. 改用本地字体加载(彻底解决字体请求问题)
将Poppins字体文件下载到项目的public/font目录(比如Poppins-Regular.ttf、Poppins-Bold.ttf等),然后在全局CSS中通过@font-face引入:
@font-face { font-family: 'Poppins'; src: url('/font/Poppins-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; /* 确保字体加载不阻塞渲染,且优先使用本地字体 */ } @font-face { font-family: 'Poppins'; src: url('/font/Poppins-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }
2. 优化html2canvas导出逻辑,等待字体加载完成
修改导出代码,利用document.fonts.ready确保所有字体加载完毕后再执行导出,同时开启相关配置允许读取本地字体:
const vm = this // 等待字体加载完成后再导出 document.fonts.ready.then(() => { html2canvas(document.getElementById(this.chartID), { scale: vm.exportImageScale, scrollY: -window.scrollY, backgroundColor: '#121111', useCORS: true, allowTaint: true, // 允许加载本地资源,避免字体被拦截 logging: false, // 关闭日志输出,减少干扰 }).then((canvas) => { downloadLink(canvas.toDataURL(), `${this.downloadName}.png`) }) })
3. 确保D3图表元素明确指定字体
在D3生成坐标轴标签、图例文本等元素时,显式设置font-family为Poppins,避免继承问题:
// 示例:设置X轴标签字体 svg.append("text") .attr("x", width / 2) .attr("y", height + 40) .attr("text-anchor", "middle") .attr("font-family", "Poppins") .attr("font-size", 14) .text("X轴标题"); // 示例:设置图例文本字体 const legend = svg.append("g") .attr("transform", `translate(${width - 150}, 20)`); legend.selectAll("text") .data(legendData) .enter() .append("text") .attr("x", 20) .attr("y", (d, i) => i * 25 + 15) .attr("font-family", "Poppins") .text(d => d.name);
4. 若坚持使用html-to-image的优化方案
同样改用本地字体,然后调整配置避免限流:
import { toPng } from 'html-to-image'; const vm = this document.fonts.ready.then(() => { toPng(document.getElementById(this.chartID), { backgroundColor: '#121111', scale: vm.exportImageScale, cacheBust: false, // 禁用缓存破坏,避免重复请求字体 fontRendering: 'canvas', // 强制用canvas渲染字体,减少远程请求 }).then((dataUrl) => { downloadLink(dataUrl, `${this.downloadName}.png`) }).catch(err => { console.error('导出失败:', err); }) })
内容的提问来源于stack exchange,提问作者bambooleotard
相关产品推荐
相关产品推荐

