我正在尝试在Matplotlib中的图形上创建文本标签,我想使用不同的颜色突出显示某些单词。由于Matplotlib没有这样做的原生功能,我想我可以将两个文本元素放在一起,但是我无法正确对齐它们。
我找到this suggested code来获取相关的功能请求,下面的示例输出是我想要模仿的,但是我无法复制它,即使我复制了他使用的代码并将其保存到一个PNG(this就是我得到的)。 Matplotlib是否更改了API处理翻译或获取文本边界的方式?
我怎样才能做到这一点?任何指导都表示赞赏。
答案 0 :(得分:1)
您链接的代码可以通过一些小修改正常工作。这是你想要做的一个很好的例子,所以我没有发布任何真正的新代码,只是我的修改版本:
将matplotlib.pyplot导入为plt 来自matplotlib import transforms
def rainbow_text(x,y,ls,lc,**kw):
"""
Take a list of strings ``ls`` and colors ``lc`` and place them next to each
other, with text ls[i] being shown in color lc[i].
This example shows how to do both vertical and horizontal text, and will
pass all keyword arguments to plt.text, so you can set the font size,
family, etc.
"""
t = plt.gca().transData
fig = plt.gcf()
#### note: this line moved down ....###
#plt.show() #
#######################################
#horizontal version
for s,c in zip(ls,lc):
text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, x=ex.width, units='dots')
#vertical version
for s,c in zip(ls,lc):
text = plt.text(x,y," "+s+" ",color=c, transform=t,
rotation=90,va='bottom',ha='center',**kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, y=ex.height, units='dots')
t = plt.gca().transData
fig = plt.gcf()
plt.show() ############### when this is here, you can see that
############### all unicorns poo rainbows ;-)
plt.figure()
rainbow_text(0.0,0.0,"all unicorns poop rainbows ! ! !".split(),
['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
size=30)
### worked on matplotlib version 1.1.0 on Debian Wheezy. Which version did you try?
答案 1 :(得分:0)
为了我自己的目的,我正在玩你的代码,并认为我只是添加我在这里所做的。
此示例是对代码的修改,允许任何文本角度旋转。但是,这仅适用于文字va='bottom'
和ha='left'
。
import math
import numpy
from numpy.linalg import inv
from matplotlib import transforms
from matplotlib import pyplot as plt
def rainbow_text(x, y, ls, lc, theta, **kwargs):
fig = plt.gcf()
axis = plt.gca()
theta_rad = math.radians(theta)
text_trans = axis.transData
for s, c in zip(ls, lc):
text = plt.text(x, y, " %s " %s,
verticalalignment='bottom',
horizontalalignment='left',
color=c,
transform=text_trans,
rotation=theta,
**kwargs)
text.draw(axis.figure.canvas.get_renderer())
# solve for the text width and height
bbox = text.get_window_extent(axis.figure.canvas.get_renderer())
theta_mat = numpy.array([[math.cos(theta_rad), math.sin(theta_rad)],
[math.sin(theta_rad), math.cos(theta_rad)]])
txt_size = numpy.dot(inv(theta_mat),
numpy.array([bbox.width, bbox.height]))
# plot the bounds for each word (only works with axis autoscaling off)
for i in range(4):
bounds = bbox.corners()
point = axis.transData.inverted().transform(bounds[i])
plt.plot(point[0], point[1], '*', color=c)
x_offset = txt_size[0] * math.cos(theta_rad)
y_offset = txt_size[0] * math.sin(theta_rad)
text_trans = transforms.offset_copy(text.get_transform(),
fig=fig,
x=x_offset,
y=y_offset,
units='points')
plt.figure()
plt.axis([0, 5, 0, 5])
rainbow_text(1, 1, "all unicorns poop rainbows ! ! !".split(),
['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
20, size=20)
plt.savefig('blarg.png', ext='png')
plt.show()