在HTML Canvas的绘图场景中,默认的字体样式很难满足个性化的视觉设计需求,给Canvas文本应用自定义字体并处理好加载逻辑,是保证绘图效果符合预期的关键步骤。自定义字体的应用需要结合CSS的字体定义和Canvas的字体属性设置,同时因为字体文件加载是异步过程,还需要做好加载状态的判断,避免出现字体未加载完成就渲染文本导致的显示异常。

Canvas文本绘制基础语法
Canvas绘制文本主要依赖两个核心方法,分别是填充文本绘制和描边文本绘制,使用前需要先设置上下文的字体属性。字体属性的设置格式和CSS的font属性一致,包含字体大小、字体族等参数。
基础的文本绘制示例如下:
// 获取Canvas元素和上下文
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 设置字体:大小 字体族
ctx.font = '24px sans-serif';
// 设置填充颜色
ctx.fillStyle = '#333';
// 绘制填充文本,参数分别为文本内容、起始x坐标、起始y坐标
ctx.fillText('默认字体文本', 50, 100);
// 设置描边颜色
ctx.strokeStyle = '#ff0000';
// 绘制描边文本
ctx.strokeText('描边文本示例', 50, 150);
自定义字体的引入方式
要让Canvas识别自定义字体,首先需要通过@font-face规则在CSS中定义字体,指定字体文件的路径和字体族名称,之后Canvas的上下文才能通过该字体族名称调用对应的自定义字体。
CSS中定义自定义字体的代码如下:
/* 定义自定义字体 */
@font-face {
font-family: 'MyCustomFont';
/* 字体文件路径,支持多种格式兼容不同浏览器 */
src: url('https://ipipp.com/fonts/my-custom-font.woff2') format('woff2'),
url('https://ipipp.com/fonts/my-custom-font.woff') format('woff');
font-weight: normal;
font-style: normal;
}
定义完成后,就可以在Canvas的font属性中使用MyCustomFont这个字体族名称,示例如下:
// 设置自定义字体
ctx.font = '24px MyCustomFont';
ctx.fillStyle = '#0066cc';
// 绘制自定义字体文本
ctx.fillText('自定义字体文本', 50, 200);
自定义字体的异步加载处理
字体文件的加载是异步过程,如果直接在定义完@font-face后就调用自定义字体绘制文本,很可能字体还没加载完成,Canvas会使用默认字体替代渲染,导致显示效果不符合预期。因此需要监听字体的加载状态,等字体加载完成后再执行绘制逻辑。
现代浏览器提供了FontFace API和document.fonts.ready接口来处理字体加载监听,推荐使用document.fonts.ready的方式,兼容性更好且使用更简单。
使用document.fonts.ready监听加载
document.fonts.ready返回一个Promise,当所有通过CSS定义的字体都加载完成后,这个Promise会变为fulfilled状态,我们可以在这个状态的回调中执行文本绘制逻辑。
// 等待所有字体加载完成
document.fonts.ready.then(() => {
// 字体加载完成后执行绘制
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 此时自定义字体已经加载完成,可以正常使用
ctx.font = '24px MyCustomFont';
ctx.fillStyle = '#333';
ctx.fillText('字体加载完成后绘制的文本', 50, 250);
}).catch(err => {
console.error('字体加载失败:', err);
// 加载失败时使用默认字体兜底
ctx.font = '24px sans-serif';
ctx.fillText('字体加载失败,使用默认字体', 50, 250);
});
单个字体加载状态判断
如果只需要监听某一个自定义字体的加载状态,可以使用FontFace API单独加载并监听该字体,示例如下:
// 创建自定义字体对象
const customFont = new FontFace('MyCustomFont', 'url(https://ipipp.com/fonts/my-custom-font.woff2)');
// 将字体添加到文档的字体集中
document.fonts.add(customFont);
// 加载字体
customFont.load().then(() => {
console.log('自定义字体加载完成');
// 执行绘制逻辑
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.font = '24px MyCustomFont';
ctx.fillText('单独加载的自定义字体文本', 50, 300);
}).catch(err => {
console.error('单个字体加载失败:', err);
});
常见问题与解决方案
- 字体不生效:检查
@font-face中定义的字体族名称和Canvas中使用的名称是否完全一致,包括大小写;检查字体文件路径是否正确,能否正常访问。 - 首次加载字体闪烁:可以在页面初始化时就触发字体加载,而不是等到需要绘制Canvas的时候再加载,提前加载可以减少用户等待时间。
- 跨域字体加载失败:如果字体文件放在不同域的服务器上,需要服务器配置CORS响应头,允许当前域访问字体资源,否则浏览器会阻止字体加载。
完整示例代码
以下是一个包含自定义字体定义、异步加载监听、Canvas文本绘制的完整示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas自定义字体示例</title>
<style>
@font-face {
font-family: 'MyCustomFont';
src: url('https://ipipp.com/fonts/my-custom-font.woff2') format('woff2'),
url('https://ipipp.com/fonts/my-custom-font.woff') format('woff');
font-weight: normal;
font-style: normal;
}
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script>
// 等待所有字体加载完成
document.fonts.ready.then(() => {
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 绘制默认字体文本
ctx.font = '20px sans-serif';
ctx.fillStyle = '#666';
ctx.fillText('默认字体示例', 50, 50);
// 绘制自定义字体文本
ctx.font = '24px MyCustomFont';
ctx.fillStyle = '#ff6600';
ctx.fillText('自定义字体异步加载示例', 50, 100);
// 绘制描边自定义字体文本
ctx.strokeStyle = '#009900';
ctx.lineWidth = 1;
ctx.strokeText('自定义描边字体', 50, 150);
}).catch(err => {
console.error('字体加载异常:', err);
});
</script>
</body>
</html>
HTML_Canvas自定义字体异步加载font_facedrawText修改时间:2026-07-11 09:27:31