Reputation: 2385
I'm using matplotlib to create annotations with arrows.
from matplotlib import pyplot as plt
plt.figure()
plt.annotate('Text1', xy=(1, 0), xytext=(1, 1), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text2', xy=(3, 0), xytext=(3, 3), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text3', xy=(6, 0), xytext=(6, 6), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text4', xy=(9, 0), xytext=(9, 9), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.xlim((0, 10))
plt.ylim(0, 10)
plt.show()
As can be seen, the length of the arrow heads is affected by the line-length and varies between the arrows.
I'm looking for a way to create arrows with different line-lengths but equal arrow-headlengths. Although many options are listed on the annotations manual page, i was not able to produce the desired result.
As an alternative approach i tried to plot the arrows seperatedely using plt.arrow. In that case the arrow heads looked as desired, but when using transparency, additional lines became visible.
Best regards, zinjaai
Upvotes: 0
Views: 2980
Reputation: 12701
In the arrowprops
you can't specify the length of the head, but the frac
arguement specifies the length of the head as a fraction the arrow length. Since you know xy
and xytext
you can compute the necessary fraction for a desired headlength.
I've don't it quickly for the example you provided (with an head length of 0.5
).
from matplotlib import pyplot as plt
plt.figure()
plt.annotate('Text1', xy=(1, 0), xytext=(1, 1),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/1))
plt.annotate('Text2', xy=(3, 0), xytext=(3, 3),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/3))
plt.annotate('Text3', xy=(6, 0), xytext=(6, 6),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/6))
plt.annotate('Text4', xy=(9, 0), xytext=(9, 9),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/9))
plt.xlim((0, 10))
plt.ylim(0, 10)
plt.show()
Result:
You could wrap this in a function, which computes the length of the arrow (given xy
and xytext
) and then passes that on to plt.annotate
.
Upvotes: 1