在利用Matplotlib开发绘图应用的过程中,有一个使用plt.text注明Markers的需求,而plt.text又无法像legend中loc有’best’设置。如果使用legend代替的话,又无法同时使用原本legend与标注Markers的需求。在网上搜索到类似的解决方法,之后突然想到一个曲线救国的方式:我们可以利用legend的loc设置为’best’,然后将legend的大小设置为和plt.text的大小一样,获取此时的legend的位置后删除legend,最后将此位置赋值给plt.text。下面是这个解决方案的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

fig, ax = plt.subplots(figsize=(9.8,6))
x = np.linspace(0.01,2*np.pi,50)
y = np.sin(x)/np.sqrt(x)
ax.plot(x, y, label="hello")
ax.plot(x, y[::-1], label="world")

line = ax.get_lines()[0]
text = "m1: x1, y1\nm2: x2, y2\nm3: x3, y3"

ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-0.5, 1)

fontsize = 20

legend = ax.legend(
[line],
[text],
loc="best",
handlelength=0,
handletextpad=0,
borderpad=0.3,
fontsize=fontsize,
frameon=True,
borderaxespad=0.15,
facecolor="none",
edgecolor="black",
fancybox=True
)
legend.get_texts()[0].set_verticalalignment("bottom")
# plt.draw()
# 更新渲染设置,plt.draw可能失效,使用下面的代码
FigureCanvas(ax.figure).draw()

xy = legend.get_texts()[0].get_window_extent().transformed(ax.transData.inverted())

legend.remove()

target_text = ax.text(xy.x0, xy.y0, text, fontsize=fontsize, bbox=dict(boxstyle="round,pad=0.3", fc="none"))

# plt.draw()
# 更新渲染设置,plt.draw可能失效,使用下面的代码
FigureCanvas(ax.figure).draw()

bbox_pos = target_text.get_bbox_patch().get_extents().transformed(ax.transData.inverted())
# 为方便显示设置_color='red',实际使用中设置为'none'
_color = "red"
ax.plot([bbox_pos.x0, bbox_pos.x0], [bbox_pos.y0, bbox_pos.y1], color=_color)
ax.plot([bbox_pos.x1, bbox_pos.x1], [bbox_pos.y0, bbox_pos.y1], color=_color)
ax.plot([bbox_pos.x0, bbox_pos.x1], [bbox_pos.y0, bbox_pos.y0], color=_color)
ax.plot([bbox_pos.x0, bbox_pos.x1], [bbox_pos.y1, bbox_pos.y1], color=_color)
ax.plot([bbox_pos.x0, bbox_pos.x1], [bbox_pos.y0, bbox_pos.y1], color=_color)
ax.plot([bbox_pos.x0, bbox_pos.x1], [bbox_pos.y1, bbox_pos.y0], color=_color)

ax.legend(prop={"size":16})

其效果如下图所示:

plt.text位置自适应
plt.text位置自适应

© 2017 - Mashiro-Sorata 使用 Stellar 创建
总访问 113701 次 | 本页访问 326