I'm trying to draw gradient text. My idea is to create a gradient using the code
Changing the limits of the axes or the width of the figure don't seem to work. I can change the size of the TextPath, but then I can't seem to make the text take up the full size of the image. Making the text size .2 and setting the ylim from 0 to .2 only makes squished text. How can I make the text span the size of the axes and take the full range of the gradient?
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import matplotlib.textpath
import matplotlib.patches
import numpy as np
def gradient_image(ax, extent, direction=0.3, cmap_range=(0, 1), **kwargs):
"""
Draw a gradient image based on a colormap.
Parameters
----------
ax : Axes
The axes to draw on.
extent
The extent of the image as (xmin, xmax, ymin, ymax).
By default, this is in Axes coordinates but may be
changed using the *transform* keyword argument.
direction : float
The direction of the gradient. This is a number in
range 0 (=vertical) to 1 (=horizontal).
cmap_range : float, float
The fraction (cmin, cmax) of the colormap that should be
used for the gradient, where the complete colormap is (0, 1).
**kwargs
Other parameters are passed on to `.Axes.imshow()`.
In particular useful is *cmap*.
"""
phi = direction * np.pi / 2
v = np.array([np.cos(phi), np.sin(phi)])
X = np.array([[v @ [1, 0], v @ [1, 1]],
[v @ [0, 0], v @ [0, 1]]])
a, b = cmap_range
X = a (b - a) / X.max() * X
im = ax.imshow(X, extent=extent, interpolation='bicubic',
vmin=0, vmax=1, **kwargs)
return im
fig, ax = plt.subplots(figsize=(1,1))
im = gradient_image(ax, direction=1, extent=(0, 1, 0, 1), transform=ax.transAxes,
cmap=plt.cm.winter, cmap_range=(0.2, 0.8), alpha=0.5)
fp = FontProperties(family='DejaVu Sans', weight='bold')
text = matplotlib.textpath.TextPath((0.0, 0.0), 'ABCDEFG',
size=1, prop=fp)
im.set_clip_path(text, transform=ax.transAxes)
# ax.set_xticks(())
# ax.set_yticks(())
# ax.tick_params(width=0, which='both')
# ax.set_xlim((0, 10))
# ax.set_ylim((0, 1))
for spine in ['top', 'bottom', 'left', 'right']:
ax.spines[spine].set_visible(False)
CodePudding user response:
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import matplotlib.textpath
import matplotlib.patches
import numpy as np
def gradient_image(ax, extent, direction=0.3, cmap_range=(0, 1), **kwargs):
"""
Draw a gradient image based on a colormap.
Parameters
----------
ax : Axes
The axes to draw on.
extent
The extent of the image as (xmin, xmax, ymin, ymax).
By default, this is in Axes coordinates but may be
changed using the *transform* keyword argument.
direction : float
The direction of the gradient. This is a number in
range 0 (=vertical) to 1 (=horizontal).
cmap_range : float, float
The fraction (cmin, cmax) of the colormap that should be
used for the gradient, where the complete colormap is (0, 1).
**kwargs
Other parameters are passed on to `.Axes.imshow()`.
In particular useful is *cmap*.
"""
phi = direction * np.pi / 2
v = np.array([np.cos(phi), np.sin(phi)])
X = np.array([[v @ [1, 0], v @ [1, 1]],
[v @ [0, 0], v @ [0, 1]]])
a, b = cmap_range
X = a (b - a) / X.max() * X
# added origin = lower, elsewise text is flipped upside down
im = ax.imshow(X, extent=extent, interpolation='bicubic',
vmin=0, vmax=1, origin='lower', **kwargs)
return im
fig, ax = plt.subplots(figsize=(1, 1))
# define text before gradient to get extent
fp = FontProperties(family='DejaVu Sans', weight='bold')
text = matplotlib.textpath.TextPath((0.0, 0.0), 'ABCDEFG',
size=1, prop=fp)
# use text to define imshow extent
extent = text.get_extents().extents[[0, 2, 1, 3]]
im = gradient_image(ax, direction=1, extent=extent,
cmap=plt.cm.winter, cmap_range=(0.2, 0.8), alpha=0.5)
# use transData instead of transAxes
im.set_clip_path(text, transform=ax.transData)
# © trenton
ax.spines[['top', 'bottom', 'left', 'right']].set_visible(False)
plt.show()