You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Matplotlib的TextPath沿任意路径绘制文本及处理文本尺寸问题

在Matplotlib中实现类似SVG textPath 的沿路径绘文本功能

我想在Matplotlib中实现类似SVG的textPath功能,让文本沿任意路径绘制。已知可以通过子类化Text类实现,但我更倾向于使用TextPath,因为它在绘图域变化时的缩放效果更好。

下面是一个非通用的示例,展示了基本思路:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import text as mtext
from matplotlib import patches as mpatch
from matplotlib import transforms as mtrans

fig, ax = plt.subplots(1, 1, figsize=(7, 7), dpi=100)

N = 100
cx = -np.cos(np.linspace(0, 2*np.pi, N))
cy = np.sin(np.linspace(0, 2*np.pi, N))

ax.plot(cx, cy, color='black')

tpath = mtext.TextPath((0, 0), 'T', .5)
tw = tpath.get_extents().width
th = tpath.get_extents().height
angle = np.rad2deg(np.arctan2(cy[0], cx[0]))
tpath = tpath.transformed(
    mtrans.Affine2D()
    .translate(-0.5 * tw, -0.5 * th)
    .rotate_deg(angle - 90)
    .translate(cx[0], cy[0])
)

tpath2 = mtext.TextPath((0, 0), 'E', .5)
tw2 = tpath2.get_extents().width
th2 = tpath2.get_extents().height
angle2 = np.rad2deg(np.arctan2(cy[5], cx[5]))
tpath2 = tpath2.transformed(
    mtrans.Affine2D()
    .translate(-0.5 * tw, -0.5 * th)
    .rotate_deg(angle2 - 90)
    .translate(cx[5], cy[5])
)

tpath3 = mtext.TextPath((0, 0), 'S', .5)
tw3 = tpath3.get_extents().width
th3 = tpath3.get_extents().height
angle3 = np.rad2deg(np.arctan2(cy[11], cx[11]))
tpath3 = tpath3.transformed(
    mtrans.Affine2D()
    .translate(-0.5 * tw, -0.5 * th)
    .rotate_deg(angle3 - 90)
    .translate(cx[11], cy[11])
)

tpath4 = mtext.TextPath((0, 0), 'T', .5)
tw4 = tpath4.get_extents().width
th4 = tpath4.get_extents().height
angle4 = np.rad2deg(np.arctan2(cy[16], cx[16]))
tpath4 = tpath4.transformed(
    mtrans.Affine2D()
    .translate(-0.5 * tw, -0.5 * th)
    .rotate_deg(angle4 - 90)
    .translate(cx[16], cy[16])
)

tpatch = mpatch.PathPatch(tpath, facecolor='red', edgecolor='black',
                          linewidth=3)
tpatch2 = mpatch.PathPatch(tpath2, facecolor='red', edgecolor='black',
                           linewidth=3)
tpatch3 = mpatch.PathPatch(tpath3, facecolor='red', edgecolor='black',
                           linewidth=3)
tpatch4 = mpatch.PathPatch(tpath4, facecolor='red', edgecolor='black',
                           linewidth=3)

ax.add_patch(tpatch)
ax.add_patch(tpatch2)
ax.add_patch(tpatch3)
ax.add_patch(tpatch4)

plt.show()

示例效果

显然,这个示例中的文本间距是硬编码的。要实现通用功能,需要针对任意路径计算文本放置点的角度,同时要准确获取文本尺寸以合理设置间距。我曾考虑子类化TextPath或创建可被TextToPath处理的Path子类,查看源码后发现这些类使用matplotlib._text_helpers模块计算文本尺寸,但不清楚其计算单位(推测为像素,但无文档说明)。希望能得到处理文本尺寸问题的更佳方案,也欢迎分享其他沿曲线路径添加文本的思路。

内容的提问来源于stack exchange,提问作者nawendt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:39:56