在条内绘制箭头的一个选项确实是孵化。然而,这有点涉及。需要创建一些自定义孵化,如以下答案所示:How to fill a polygon with a custom hatch in matplotlib? 在这里我们可以使用箭头的路径。
因此,在下面我们继承matplotlib.hatch.Shapes 并创建一些箭头路径。现在的问题是我们需要一些参数来插入阴影,以便能够定义角度。然后我们可以定义一个自定义的阴影图案,我选择看起来像这样
hatch="arr{angle}{size}{density}"
在哪里
- 角度:0到360之间的整数
- 大小:2 到 20 之间的某个整数
- 密度:某个整数 >= 1
这与我之前在this question 上的回答类似。
根据路径旋转的角度,大小和密度基本上决定了显示多少个大小的箭头。请注意,并非所有参数看起来都很好,有些参数会导致阴影重叠。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.offsetbox
import matplotlib.hatch
from matplotlib.patches import Polygon
class ArrowHatch(matplotlib.hatch.Shapes):
"""
Arrow hatch. Use with hatch="arr{angle}{size}{density}"
angle: integer number between 0 and 360
size: some integer between 2 and 20
density: some integer >= 1
"""
filled = True
size = 1
def __init__(self, hatch, density):
v1 = [[.355,0], [.098, .1], [.151,.018], [-.355,.018]]
v2 = np.copy(v1)[::-1]
v2[:,1] *= -1
v = np.concatenate((v1,v2))
self.path = Polygon(v, closed=True, fill=False).get_path()
self.num_lines = 0
if len(hatch) >= 5:
if hatch[:3] == "arr":
h = hatch[3:].strip("{}").split("}{")
angle = np.deg2rad(float(h[0]))
self.size = float(h[1])/10.
d = int(h[2])
self.num_rows = 2*(int(density)//6*d)
self.num_vertices = (self.num_lines + 1) * 2
R = np.array([[np.cos(angle), -np.sin(angle)],
[np.sin(angle), np.cos(angle)]])
self.shape_vertices = np.dot(R,self.path.vertices.T).T
self.shape_codes = self.path.codes
matplotlib.hatch.Shapes.__init__(self, hatch, density)
matplotlib.hatch._hatch_types.append(ArrowHatch)
n = 7
a = 1017
x = np.arange(n)
y = np.linspace(0.2*a,a,len(x))
fig, ax = plt.subplots()
bar = ax.bar(x,y, ec="k", color="lightblue")
angles = [0,45,360-45,90,225,360-90,160]
for b, a in zip(bar, angles):
f = 'arr{{{}}}{{9}}{{3}}'.format(a)
b.set_hatch(f)
plt.show()
{angle}{9}{3} 的输出:
输出{angle}{11}{2}:
下面解释了孵化模式以及如何管理它们。或者换句话说,
ArrowHatch 怎么知道它应该创建一个孵化?
将使用
matplotlib.hatch._hatch_types 内的任何影线的顶点应用影线。这就是为什么我们需要将我们的
ArrowHatch 类附加到这个列表中。取决于此类是否具有大于零的属性
num_vertices,它将有助于最终孵化。这就是我们在 init 函数中将其设置为
self.num_lines = 0 的原因。但是,如果
hatch(提供给
_hatch_types 列表中的每个类的字符串)包含我们的匹配模式,我们将
self.num_rows 设置为0 以外的值(对于Shapes,它应该是偶数,因为它们是生成的在 2 个移动的行中),这样它可以有助于孵化。
这个概念有点异国情调,因为基本上每个班级自己决定是否参与孵化取决于
hatch 字符串。一方面,这非常方便,因为它可以轻松组合不同的舱口类型,例如
"///++oo"。另一方面,它很难用于需要输入参数的影线,在这种情况下是角度。并且还需要注意不要在孵化中使用任何角色,这些角色会被其他孵化使用;例如,我最初想使用
"arrow45.8,9,2" 之类的东西,但它不起作用,因为
o、
. 和
, 是其他有效的阴影类型,因此结果会在整个地方显示一些点。