canvas filltext 不支持 \n 换行,因其不解析换行符;正确做法是按空格拆词后逐词测量宽度,无空格时需逐字符测量,避免按固定字数截断导致宽度不准。

Canvas fillText 传入 \n 为什么无效
因为 Canvas API 的 fillText 方法本身不解析换行符——无论你传入 "第一行\n第二行" 还是带多个 \n 的字符串,它都当作一整段纯文本测量并绘制,\n 被忽略。这不是 UniApp 的 bug,而是 HTML5 Canvas 规范行为,所有平台(包括微信小程序)都一样。
手动分段必须用 ctx.measureText,不能靠字符数截取
按固定字数(比如每行 10 个汉字)硬切,会因字体、字号、中英文混排导致宽度严重不准,尤其在 iOS 小程序上偏差更大。正确做法是逐字符或逐词测量:
- 推荐按空格拆词:
text.split(' '),再逐个累加测试宽度 - 若文本无空格(如长数字、URL、连续英文),需逐字符测量:
for (let i = 0; i - 每次调用
ctx.measureText(str).width前,确保已设置好ctx.font,否则测量结果不可靠 - 注意:不同设备像素比会影响
measureText返回的width,建议用getSystemInfoSync().pixelRatio校准最大宽度
行高和最后一行容易漏绘
常见错误是只处理了“超宽换行”,却忘了绘制循环结束后的剩余文本。同时,行高不能简单写死 20 或 22:
- 行高应基于字体大小动态计算,例如
y += fontSize * 1.4 - 循环内每次
fillText后更新y,但循环结束后,若line非空,必须再调一次fillText(line, x, y) - 如果限制最多显示 3 行,需在第 3 行末尾手动加
"…",且要重新测量截断后宽度,避免溢出
小程序真机调试时字体渲染差异大
开发工具里看着正常,真机上文字挤在一起或错位,大概率是字体 fallback 导致的:
- 避免只设
ctx.font = "14px sans-serif",iOS 和安卓默认字体不同,measureText结果差异可达 20% - 统一指定字体栈:
ctx.font = "14px -apple-system, system-ui, Helvetica Neue" - 关键场景下,可预估平均字符宽度(如中文约
fontSize * 0.9),用于快速初筛,再用measureText精修
实际换行逻辑必须自己实现,没有“开启自动换行”开关。最易被忽略的是:测量与绘制使用的 font 必须完全一致,且最后一行是否补绘、是否加省略号,都要显式判断。










