measureText() 返回当前 ctx.font 设置下文本的渲染宽度(px),但必须先完整设置字体样式(含字号、字重、字体族),否则结果偏差极大;仅 width 属性可靠,且需确保字体已加载完成。

measureText() 返回的是当前 ctx.font 设置下文本的**渲染宽度(单位:px)**,但它不是“开箱即用”的精确值——必须先配对字体样式,否则结果偏差极大,甚至相差 2–3 倍。
必须先设置完整的 ctx.font 字符串
浏览器不会自动继承页面 CSS 字体,ctx.font 默认是 "10px sans-serif"。如果你没显式赋值就调用 measureText(),它就按这个默认值算,和你最终 fillText() 时用的实际字体完全不匹配。
-
ctx.font = "bold 16px 'Microsoft YaHei', sans-serif"—— 中文推荐带引号,避免解析歧义 - 字号、字重、字体族缺一不可;只写
"16px"或"Arial"都会导致测量失效 - 中英文混排时,不同字体对空格、标点、全角字符的宽度处理差异大,建议 fallback 到统一字体(如
sans-serif)
measureText() 返回对象只有 width 属性可靠
虽然返回的是 TextMetrics 对象,但只有 .width 是广泛支持且稳定的。其他属性如 actualBoundingBoxLeft 或 emHeightAscent 在 Safari 和旧版 Chrome 中行为不一致,生产环境别依赖。
- 正确用法:
const w = ctx.measureText("Hello").width - 错误写法:
ctx.measureText("Hello").actualBoundingBoxLeft—— 不跨浏览器 - 注意:该方法不触发重绘,纯计算,可放心在循环或高频逻辑中调用
常见误差来源:字体加载未完成 or 字体回退失败
如果页面用了 @font-face 自定义字体,但调用 measureText() 时字体还没加载完,浏览器会回退到系统字体(比如从 “PingFang SC” 回退到 “Helvetica”),导致宽度突变。
立即学习“前端免费学习笔记(深入)”;
- 检测方式:对比
getComputedStyle(document.body).fontFamily和你设的ctx.font是否一致 - 稳妥做法:监听
document.fonts.load(),或用FontFaceSet.check()确认字体就绪后再测 - 降级方案:若无法等字体加载,至少保证 fallback 字体(如
sans-serif)在ctx.font中明确写出
真正容易被忽略的不是 API 怎么调,而是字体状态是否可控——measureText() 测的从来不是字符串长度,而是「此刻画布上下文所见的、已加载完毕的、完整声明的字体」下的渲染结果。字体没落定,宽度就不算数。



















