canvas文本自动换行需手动按像素宽度分段绘制,核心是逐字符累加测宽并动态断行,须预设字体、处理中英文混排与特殊字符,支持回退断行、省略号、空白过滤及封装复用。

Canvas 文本自动换行不能靠 CSS,必须手动计算字符宽度并分段绘制。核心不是“按字数切”,而是“按像素宽切”——尤其对中英文混排、全角/半角、不同字体影响显著。
先设好字体,再测宽
ctx.font 必须提前设置(如 ctx.font = '14px "Microsoft YaHei", sans-serif'),否则 measureText 返回的宽度不可靠。字体未生效时测出来的值会严重失真,导致断行错位甚至死循环。
- 推荐显式声明字体族和字号,避免依赖浏览器默认
- 中文字体建议包含 fallback(如 sans-serif),防止某些系统缺失字体时回退异常
- 同一 canvas 上若需多字体混排,每次切换字体后都需重新 measureText
逐字符累加 + 动态断行
把字符串转成字符数组(Array.from(str)),确保正确处理 emoji、代理对等复杂字符。维护一个当前行字符串和累计宽度,边拼边测:
- 拼入下一个字符后,用 ctx.measureText(line + char).width 判断是否超限
- 没超就保留;超了就绘制当前行,新行从该字符开始(不是丢弃)
- 若单个字符本身宽度 > maxWidth(比如超长 URL 或 emoji 组合),强制单独成行,避免卡死
照顾可读性的小细节
纯算法能跑通,但真实场景需要微调体验:
- 英文单词内尽量不断开:遇到空格或标点时,尝试回退到前一个空格处断行
- 末行放不下时,用 line.slice(0, -1) + '…' 替代截断,并重测宽度确保省略号不溢出
- 每行绘制前 .trim(),过滤首尾空白,避免因原始文本带换行符或缩进而多出空行
- 固定字体+高频文本场景下,可预建 ASCII + 常用汉字宽度查表,减少重复 measureText 调用
封装成可复用函数
把逻辑收拢为带参数的绘图函数,调用更直观:
- 输入:ctx、文本、起始坐标 (x, y)、最大宽度、行高、对齐方式(左/居中/右)
- 输出:自动分行、逐行 fillText,支持垂直居中等常见布局需求
- 可扩展:加入两端对齐(通过字符间距微调)、省略号位置控制、换行失败兜底机制











