您可以使用以下类沿行创建文本。它取两个点(
p和
pa)作为输入,而不是一个角度。这两个点之间的连接定义了数据坐标中的角度。如果
pa未给出,则使用
p和之间的连接线
xy(文本坐标)。
然后,角度会自动更新,以使文本始终沿直线定向。这甚至适用于对数刻度。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.text as mtextimport matplotlib.transforms as mtransformsclass RotationAwareAnnotation(mtext.Annotation): def __init__(self, s, xy, p, pa=None, ax=None, **kwargs): self.ax = ax or plt.gca() self.p = p if not pa: self.pa = xy self.calc_angle_data() kwargs.update(rotation_mode=kwargs.get("rotation_mode", "anchor")) mtext.Annotation.__init__(self, s, xy, **kwargs) self.set_transform(mtransforms.IdentityTransform()) if 'clip_on' in kwargs: self.set_clip_path(self.ax.patch) self.ax._add_text(self) def calc_angle_data(self): ang = np.arctan2(self.p[1]-self.pa[1], self.p[0]-self.pa[0]) self.angle_data = np.rad2deg(ang) def _get_rotation(self): return self.ax.transData.transform_angles(np.array((self.angle_data,)), np.array([self.pa[0], self.pa[1]]).reshape((1, 2)))[0] def _set_rotation(self, rotation): pass _rotation = property(_get_rotation, _set_rotation)
用法示例:
fig, ax = plt.subplots()t = np.arange(0.0, 1.0, 0.01)line, = ax.plot(t, t, color='blue', lw=2)ra = RotationAwareAnnotation("test label", xy=(.5,.5), p=(.6,.6), ax=ax, xytext=(2,-1), textcoords="offset points", va="top")plt.show()
边缘盒的替代品
在某些情况下,在沿垂直线或x和y单位高度不同的文本上,上述 *** 作可能会失败。在这种情况下,以下内容将更适合。它以屏幕坐标为单位计算角度,而不是依靠角度变换。
class RotationAwareAnnotation2(mtext.Annotation): def __init__(self, s, xy, p, pa=None, ax=None, **kwargs): self.ax = ax or plt.gca() self.p = p if not pa: self.pa = xy kwargs.update(rotation_mode=kwargs.get("rotation_mode", "anchor")) mtext.Annotation.__init__(self, s, xy, **kwargs) self.set_transform(mtransforms.IdentityTransform()) if 'clip_on' in kwargs: self.set_clip_path(self.ax.patch) self.ax._add_text(self) def calc_angle(self): p = self.ax.transData.transform_point(self.p) pa = self.ax.transData.transform_point(self.pa) ang = np.arctan2(p[1]-pa[1], p[0]-pa[0]) return np.rad2deg(ang) def _get_rotation(self): return self.calc_angle() def _set_rotation(self, rotation): pass _rotation = property(_get_rotation, _set_rotation)
在通常情况下,两者都会产生相同的输出。我不确定第二堂课是否有缺点,所以我将两者都留在这里,选择您认为更合适的那个。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)