'Text object in matplotlib doesn't respond to zooming properly
. Hello, everyone.
I recently try to add text object in my plot. But when I zoom into the text, the text size remains unchanged. What I want to have is that the text size will increase when I zoom in and will decrease when I zoom out.
import matplotlib as mpl
fig=plt.figure()
ax1=fig.add_subplot(111)
ax1.text('','', '',position=[0.5,0.5], text='Y', fontsize='xx-small' )
Any help is appreciated. Thanks~
Supplement-UTC+8 30/04/2013 9:40 AM
Thanks for the suggestion from tcaswell. TextPath does achieve part of my purposes.
I found there is no documentation about textpath in official matplotlib website, so I view the source code to see what it does. Finally, I achieved a not excellent but satisfactory result as follows.
from matplotlib.textpath import TextPath
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path
fig=plt.figure()
ax1=fig.add_subplot(111)
tp1=TextPath((0.5,0.5), r'How do you turn this on?', size=1)
polygon=tp1.to_polygons()
for a in polygon:
p1=patches.Polygon(a)
ax1.add_patch(p1)
The not excellent part of this code is that it doesn't support rotation and export the text as filled polygon. Is there any easy way to rotate the text? Can I export the text as non-filled polygon?
Solution 1:[1]
When you create a Polygon instance, you can specify many keyword arguments, including setting fill = False (see details here):
from matplotlib.textpath import TextPath
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path
fig=plt.figure()
ax1=fig.add_subplot(111)
ax1.set_ylim(-1 , 3)
ax1.set_xlim(-3, 15)
tp1=TextPath((0.0,0.5), r'How do you turn this on?', size=1)
polygon=tp1.to_polygons()
for a in polygon:
p1=patches.Polygon(a, fill=False)
ax1.add_patch(p1)
plt.show()
Solution 2:[2]
Thanks for the question and the pre-work! My solution is just called by the command:
text_fixed_size(ax=ax, text=f'pos=(4,8), h=1', pos=(4,8), h=1, color=c)
and produces the orange output in the following (solid text and holes, like in 'o', not filled) picture. This solution also works for inverted axes. Height and width can be set independently, if needed.
Code
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
def text_fixed_size(ax, text, pos, w=None, h=None, auto_trans=True, color='k'):
assert not (w is None and h is None)
tp = mpl.textpath.TextPath((0.0,0.0), text, size=1)
x0, y0 = np.amin(np.array(tp.vertices), axis=0)
x1, y1 = np.amax(np.array(tp.vertices), axis=0)
hax = -np.subtract(*ax.get_xlim())
wax = -np.subtract(*ax.get_ylim())
if w is None:
w = h / (y1 - y0) * ( x1 - x0)
if h is None:
h = w / (x1 - x0) * ( y1 - y0)
if auto_trans:
w *= np.sign(hax)
h *= np.sign(wax)
verts = []
for vert in tp.vertices:
vx = vert[0] * w / (x1 - x0) + pos[0]
vy = vert[1] * h / (y1 - y0) + pos[1]
verts += [ [vx, vy] ]
verts = np.array(verts)
tp = mpl.path.Path(verts, tp.codes)
ax.add_patch(mpl.patches.PathPatch(tp, facecolor=color, lw=0))
fig, axs = plt.subplots(2, 2)
axs = np.array(axs).T.flatten()
lims = np.array([[0, 15], [0,10]])
for aa, ax in enumerate(axs):
d0 = int((-(aa%2)+.5)*2)
d1 = int((-(aa//2)+.5)*2)
l = np.array([lims[0, ::d0], lims[1, ::d1]])
ax.set_xlim(l[0, 0], l[0, 1])
ax.set_ylim(l[1, 0], l[1, 1])
for aa, ax in enumerate(axs):
c = 'C0'
text_fixed_size(ax=ax, text=f'pos=(6,3), w=5, h=1',
pos=(6,3), w=5, h=1, color=c)
c = 'C1'
text_fixed_size(ax=ax, text=f'pos=(4,8), h=1',
pos=(4,8), h=1, color=c)
c = 'C2'
text_fixed_size(ax=ax, text=f'pos=(8,1), w=5, auto_trans=False',
pos=(3,1), w=10, auto_trans=False, color=c)
plt.show()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | edwinksl |
| Solution 2 | Markus Dutschke |


