canvas不支持自动弧线排版文字,需手动拆分字符、用三角函数计算圆周坐标,并通过translate和rotate逐个绘制;推荐按字宽加权分配弧长以提升视觉均匀性。

Canvas 本身不支持自动沿弧线排版文字,必须手动计算每个字符在圆弧上的位置并逐个绘制。核心是把字符串拆成单字符,用三角函数算出它们在圆周上的坐标,再配合 translate 和 rotate 让每个字符“面向圆心”或“切线方向”对齐。
确定圆弧参数和字符分布
先定义圆心 (cx, cy)、半径 r、起始角度 startAngle(弧度)、结束角度 endAngle。总弧度跨度为 span = endAngle - startAngle。若字符串长度为 n,则每个字符平均占弧度 angleStep = span / n(注意:这不是强制等分,可按字宽加权,但等分最常用)。
- 角度单位统一用弧度——所有
Math.sin/Math.cos都要求弧度 - 起始角通常从 0(正右方)或 -π/2(正上方)开始,取决于你想要的起始方位
- 中文或等宽字体可直接等分;英文建议用
measureText测量单字符宽度后加权分配弧长,避免挤在一起
逐字符定位与旋转绘制
对第 i 个字符,计算其所在圆弧点的坐标:x = cx + r * Math.cos(startAngle + i * angleStep)y = cy + r * Math.sin(startAngle + i * angleStep)
接着用 context.save() 保存状态,再执行:
-
context.translate(x, y)移动原点到该点 -
context.rotate(startAngle + i * angleStep + Math.PI/2)—— 加π/2是让文字朝向切线方向(竖直向上为 0 弧度时);若要朝向径向(指向圆心),改用startAngle + i * angleStep + Math.PI - 调用
fillText(char, 0, 0)或strokeText(char, 0, 0),此时 (0,0) 就是当前字符位置 -
context.restore()恢复坐标系,为下一个字符做准备
优化可读性与视觉效果
纯等角度排布容易造成首尾稀疏、中间拥挤(尤其英文)。更自然的做法是按实际字宽分配弧长:
- 先用
ctx.measureText(char).width获取每个字符宽度,累加得总宽度totalWidth - 将总弧长
r * span按各字符宽度比例分配,得到每个字符对应的弧度增量 - 再积分求出每个字符的累计弧度,代入上面公式计算位置
- 为避免字符倒置,可在
rotate后检查角度是否超出 ±π/2,必要时翻转scale(1, -1)并调整y偏移
兼容性与调试技巧
实际项目中建议封装为函数,例如 drawArcText(ctx, text, cx, cy, r, startAngle, endAngle, options),并支持选项如:
-
align: 'center' | 'left' | 'right'—— 控制整段文字在弧上的水平偏移(如居中对齐弧段中点) -
direction: 'clockwise' | 'counterclockwise'—— 影响角度递增方向 -
baseline: 'alphabetic' | 'ideographic'—— 中文推荐ideographic,更贴合字面顶部 - 调试时可用
strokeCircle(cx, cy, r)画参考圆,再用小圆点标出每个字符落点,确认轨迹是否符合预期
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











