Canvas文字测量需先确保font样式完整设置且字体就绪,measureText.width是唯一跨浏览器稳定的宽度值,其他TextMetrics属性不可靠,多行文本须手动处理。

Canvas 里文字没有盒子模型,measureText 不是“算长度”,而是测当前字体设置下真实渲染出来的像素宽度。关键不在 API 怎么调,而在字体是否就绪、样式是否完整、测量逻辑是否匹配实际绘制场景。
必须先设好 font 样式
ctx.font 必须显式赋值,且包含字号、字重、字体族三要素。浏览器不会继承 CSS 字体,也不自动 fallback。只写 "16px" 或 "Arial" 都会导致测量偏差,甚至翻倍。
- 推荐写法:
ctx.font = "bold 14px 'PingFang SC', 'Microsoft YaHei', sans-serif" - 中文字体名带空格时加引号,避免解析错误
- 中英文混排建议指定统一 fallback(如
sans-serif),减少宽度跳变
measureText 返回的 width 是唯一可靠字段
TextMetrics 对象里只有 .width 属性跨浏览器稳定可用。其他如 actualBoundingBoxLeft、emHeightAscent 在 Safari 和旧版 Chrome 中行为不一致,生产环境别依赖。
- 正确用法:
const w = ctx.measureText("订单已支付").width - 错误写法:
ctx.measureText("订单").actualBoundingBoxRight - 该方法纯计算,不触发渲染,可放心在循环或高频逻辑中调用
字体加载未完成是常见误差根源
用了 @font-face 自定义字体,但没等它加载完就调 measureText,浏览器会回退到系统字体,导致宽度突变——你测的是 Helvetica,画出来却是 PingFang,对不上。
- 检测方式:对比
getComputedStyle(document.body).fontFamily和你设的ctx.font - 稳妥做法:用
document.fonts.load("14px 'YourFont'")或FontFaceSet.check()确认就绪再测 - 降级方案:至少保证
ctx.font末尾明确写出 fallback 字体(如sans-serif)
宽度 ≠ 行高,也不含上下留白
measureText 的 width 仅反映字符水平方向的渲染宽度,不包含行高、字间距、上下 padding 或 baseline 偏移。如果你要做垂直居中或气泡自适应高度,得额外估算或实测行高。
- 行高建议用
fontSize * 1.2 ~ 1.4估算,或通过ctx.measureText("M").actualBoundingBoxAscent + ctx.measureText("M").actualBoundingBoxDescent实测(注意兼容性) - 多行文本需手动分词+逐行累加宽度,Canvas 本身不支持自动换行
- 截断、缩放、换行等自适应效果,都建立在 width 测量准确的基础上


















