API reference¶
The package exposes a function and an artist class. Use the curved_text
function for the common case. Use the CurvedText class when you need to keep a
reference to the label and change it after drawing.
- curved_text.curved_text(ax: Axes, x: ArrayLike, y: ArrayLike, text: str, *, pos: float = 0.5, anchor: str = 'center', offset: float = 0.0, box: bool | str | dict = False, crowding: str = 'none', valign: str = 'center', **kwargs: Any) CurvedText[source]¶
Draw
textalong the curve(x, y)onaxand return the artist.Thin convenience wrapper around
CurvedText; see it for the meaning ofpos,anchor,offset,box,crowding, andvalign. The axes is the first argument here, matching matplotlib’s axes-first helper functions, whereasCurvedTexttakes it afterx, y, textto matchmatplotlib.text.Text.
- class curved_text.CurvedText(x: ArrayLike, y: ArrayLike, text: str, axes: Axes, *, pos: float = 0.5, anchor: str = 'center', offset: float = 0.0, box: bool | str | dict = False, crowding: str = 'none', valign: str = 'center', **kwargs: Any)[source]¶
Bases:
TextA string drawn along an (x, y) curve, one segment at a time (each plain character and each
$...$run).Every glyph – plain character or mathtext run – is laid out on one shared text baseline and mapped onto the curve from its glyph outline: a plain character rigidly (one rotation by the chord across its own advance, so its shape is undistorted), a mathtext run by bending its outlines so radicals and fractions stay connected.
valignchooses which line of the text rides the curve – the vertical centre by default. Because both kinds share the baseline, plain and math sit level by construction, and because each glyph is placed by an isometry there is no per-glyph drift. The rotation chord follows the local tangent but averages over the glyph’s own width, so rotation stays smooth across the vertices of a coarsely sampled polyline instead of snapping to each segment’s angle. The layout is recomputed on every draw, so the label keeps following the curve through figure layout, resizing, and interactive panning or zooming.Placement controls:
posWhere the label is anchored along the curve, as a fraction of the curve’s arc length:
0.0is the first point,1.0is the last.anchorWhich part of the label lands at
pos:"start","center", or"end".offsetA perpendicular shift off the curve, in typographic points. The label is laid along the parallel (offset) curve at that distance, so the clearance from the curve is uniform along the whole label and the letter spacing stays even, even where the curvature is steep or asymmetric. Positive is to the left of the direction of travel, which is visually above a left-to-right curve.
posandanchorstay measured against the original curve and are carried perpendicularly onto the offset curve, so an offset label sits directly off the spot the sameposmarks on the bare curve.valignWhich line of the text rides the curve:
"center"(the default – the text straddles the curve),"baseline"(the baseline follows the curve, so the body sits above it with descenders below),"ascender", or"descender". The choice is a single font-metric shift applied identically to every glyph and to the mathtext runs, so it never introduces a per-glyph step and keeps plain and math aligned. Combine withoffsetto lift the chosen line off the curve.
A label that overruns either end of the curve – because of
posandanchor– is not clipped. The curve is extended along its end tangent and the overrunning glyphs are placed on that straight extension.Set
boxto draw a casing behind the label – a band that follows the curve at the label’s height, drawn under the glyphs – so the label stays legible where it crosses the lines it labels. For a lighter, glyph-hugging casing instead, pass a whitewithStrokethroughpath_effects; a wide stroke there merges adjacent per-character glyphs, soboxis the way to get solid coverage under plain text.Mathtext is supported: each
$...$run intextis laid out by matplotlib’s mathtext engine and bent continuously along the curve – every glyph outline and rule box is mapped through the curve’s arc-length frame, so radicals, fractions, and sized delimiters stay connected at any curvature. The run rides the same baseline as the surrounding plain glyphs, so its main symbols sit level with them. Passparse_math=Falseto treat dollar signs literally.text.usetexis not supported. Tall expressions compress vertically on the inside of tight bends, so choose label size relative to curvature accordingly.Both plain glyphs and mathtext runs are rendered from their glyph outlines rather than as hinted
Textartists. On a rotated label this is what lets a single baseline be pinned exactly; the only cost is the loss of pixel-grid hinting, which is marginal on rotated text and matches how mathtext has always rendered.- Parameters:
x (array-like) – The curve in data coordinates: 1-D, equal length, at least two points, finite, and ordered along the curve.
y (array-like) – The curve in data coordinates: 1-D, equal length, at least two points, finite, and ordered along the curve.
text (str) – The string to draw. May contain mathtext runs (
$...$).axes (matplotlib.axes.Axes) – The axes to draw into.
pos (float, default 0.5) – Arc-length fraction in
[0, 1]for the anchor point.anchor ({"start", "center", "end"}, default "center") – Which part of the label sits at
pos.offset (float, default 0.0) – Perpendicular offset off the curve, in points. The label is laid along the parallel (offset) curve at that distance.
box (bool, str, or dict, default False) – A casing drawn behind the label to clear the lines it crosses.
Truedraws a white band; a color string sets its color; a dict acceptscolor,pad(band height relative to the tallest glyph, default1.1), andalpha. The band has rounded ends, so it extends about half its height past the first and last glyph.crowding ({"none", "curvature"}, default "none") – How to space glyphs around bends.
"none"advances each glyph by its own width, so on the concave side of a tight bend the rotated glyph boxes can overlap."curvature"opens an even letterspacing gap that grows with the local curvature and the glyph height, so the inside edges stop colliding; the gap is the same between every pair of letters, and a deadband leaves gentle bends and straight runs unchanged.valign ({"center", "baseline", "ascender", "descender"}, default "center") – Which line of the text rides the curve.
"center"straddles the text on the curve (the default);"baseline"follows the text baseline so the body sits above the curve; the others ride the ascender or descender line. Each is a constant font-metric shift applied to the whole label.**kwargs – Passed to each per-character glyph and each mathtext run (for example
color,fontsize,alpha,fontfamily).
- set_zorder(zorder) None[source]¶
Set the zorder for the artist. Artists with lower zorder values are drawn first.
- Parameters:
level (float)
- remove() None[source]¶
Remove the artist from the figure if possible.
The effect will not be visible until the figure is redrawn, e.g., with .FigureCanvasBase.draw_idle. Call ~.axes.Axes.relim to update the Axes limits if desired.
Note: there is no support for removing the artist’s legend entry.
- draw(renderer, *args, **kwargs) None[source]¶
Draw the Artist (and its children) using the given renderer.
This has no effect if the artist is not visible (.Artist.get_visible returns False).
- Parameters:
renderer (~matplotlib.backend_bases.RendererBase subclass.)
Notes
This method is overridden in the Artist subclasses.