Home > database >  How to create gradient text with a clipped background
How to create gradient text with a clipped background

Time:09-01

I'm trying to draw gradient text. My idea is to create a gradient using the code enter image description here

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?

enter image description here

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:

I am not fully fluent in enter image description here

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()
  • Related