如何在Canvas中使用@font-face自定义字体无需页面元素预加载?
如何在Canvas中直接使用未在页面元素中引用的自定义字体?
这个问题的核心原因是浏览器的字体懒加载机制:为了优化性能,浏览器只会加载那些被页面DOM元素实际使用到的字体,未被引用的字体不会主动加载,所以你在Canvas里直接调用时,字体还没加载完成,浏览器就会用系统字体替代。
你的临时方案用visibility:hidden的元素触发加载确实能生效,但确实不够优雅。这里推荐使用标准的FontFace API来主动加载字体,这才是无需依赖页面元素的最佳实践。
具体实现步骤:
- 创建FontFace实例:为每个自定义字体创建对应的
FontFace对象,指定字体名称和资源路径 - 等待字体加载完成:通过
load()方法加载字体,并用Promise.all确保所有字体都加载完毕 - 添加字体到文档:加载完成后,将字体添加到
document.fonts集合中 - 绘制Canvas文本:确认字体加载完成后,再执行Canvas的绘制逻辑
完整代码示例:
window.onload = function() { // 1. 定义所有需要的自定义字体 const fontDefinitions = [ new FontFace('Amsterdam Graffiti', 'url("./fonts/amsterdam.ttf")'), new FontFace('Army Rust', 'url("./fonts/ARMY RUST.ttf")'), new FontFace('Badaboom BB', 'url("./fonts/BADABB__.TTF")') ]; // 2. 批量加载字体,全部完成后再绘制 Promise.all(fontDefinitions.map(font => font.load())) .then(loadedFonts => { // 3. 将加载好的字体添加到文档可用字体中 loadedFonts.forEach(font => document.fonts.add(font)); // 4. 现在可以安全地绘制Canvas文本了 drawCanvasContent(); }) .catch(err => { console.error('字体加载失败:', err); }); }; function drawCanvasContent() { const fontprevcanvas = document.getElementById("fontprevcanvas"); const ctx = fontprevcanvas.getContext("2d"); ctx.font='28px Amsterdam Graffiti'; ctx.textAlign = "center"; ctx.fillText('test1', 40, 40); ctx.font='28px Army Rust'; ctx.textAlign = "center"; ctx.fillText('test2', 40, 80); ctx.font='28px Badaboom BB'; ctx.textAlign = "center"; ctx.fillText('test3', 40, 120); }
为什么这个方法更好?
- 主动可控:完全不需要依赖任何DOM元素,直接通过API主动加载字体
- 时机精准:通过Promise确保所有字体加载完成后再绘制,彻底避免字体未就绪导致的 fallback
- 标准规范:
FontFace是W3C标准API,现代主流浏览器(Chrome 66+、Firefox 58+、Safari 12.1+、Edge 79+)都支持 - 错误处理:可以通过catch捕获字体加载失败的情况,方便排查问题
如果需要兼容更旧的浏览器,可以结合document.fonts.ready事件(它会在所有文档字体加载完成后触发),但优先推荐FontFace API,因为它的灵活性和可控性更强。
内容的提问来源于stack exchange,提问作者L777
相关产品推荐
相关产品推荐

