handanim.primitives package

Submodules

handanim.primitives.curves module

class handanim.primitives.curves.Curve(points: list[tuple[float, float]], *args, **kwargs)

Bases: Drawable

A class representing a curve that can be drawn with a sketchy, hand-drawn style.

Allows creating curves with multiple points, supporting various drawing techniques including single line, quadratic, and more complex multi-point curves with randomization to simulate hand-drawn appearance.

points

List of points defining the curve’s shape.

Type:

List[np.ndarray]

draw() OpsSet

Draw the curve

draw_single_curve(opsset: OpsSet, points: list[ndarray] | None = None, close_point: tuple[float, float] | ndarray | None = None) OpsSet

Draws a single human style sketchy curve

draw_single_curve_with_randomization(opsset: OpsSet, points: list[ndarray] | None = None, offset: float = 1.0) OpsSet

Draw a single human style sketchy curve with random derivations

handanim.primitives.ellipse module

class handanim.primitives.ellipse.Circle(center: tuple[float, float], radius: float, *args, **kwargs)

Bases: Ellipse

A specialized Ellipse where the x and y radii are equal, creating a perfect circle.

Parameters:
  • center (tuple[float, float]) – The center coordinates of the circle.

  • radius (float) – The radius of the circle.

class handanim.primitives.ellipse.Ellipse(center: tuple[float, float], width: float, height: float, *args, **kwargs)

Bases: Drawable

A drawable ellipse primitive with sketchy rendering capabilities.

Supports customizable center, width, height, and sketch-style rendering with optional multi-stroke and roughness effects. Allows for generating ellipses with randomized point generation and stroke variations.

center

The center point of the ellipse

Type:

np.ndarray

width

The width of the ellipse

Type:

float

height

The height of the ellipse

Type:

float

draw() OpsSet

Draw a sketchy version of an ellipse

draw_ellipse_border(opsset: OpsSet) tuple[list, OpsSet]
class handanim.primitives.ellipse.GlowDot(center: tuple[float, float], radius: float = 1, *args, **kwargs)

Bases: Drawable

A drawable glowing dot with customizable center, radius, and opacity scaling.

Renders a dot with multiple overlapping layers of decreasing opacity and increasing radius to create a glowing effect.

Parameters:
  • center (Tuple[float, float]) – The center coordinates of the dot.

  • radius (float, optional) – The base radius of the dot. Defaults to 1.

draw() OpsSet

Draw a perfect glowing dot

handanim.primitives.eraser module

class handanim.primitives.eraser.Eraser(objects_to_erase: list[Drawable], drawable_cache: DrawableCache, *args, **kwargs)

Bases: Drawable

A Drawable representing an eraser that can remove specified drawable objects.

objects_to_erase

The list of drawable objects to be erased.

Type:

List[Drawable]

drawable_cache

Cache used for calculating bounding box of objects to erase.

Type:

DrawableCache

The draw method generates a zigzag motion over the bounding box of the objects to be erased, using an expanded pen width to create a pastel blend erasing effect.

draw() OpsSet

Calculates the zigzag motion of the eraser

handanim.primitives.lines module

class handanim.primitives.lines.Line(start: tuple[float, float] | ndarray, end: tuple[float, float] | ndarray, *args, **kwargs)

Bases: Drawable

A drawable line primitive that generates hand-drawn style lines with randomized jitter and bowing effects.

Supports customizable stroke and sketch styles, with options for line curvature, roughness, and multiple line passes to create a hand-drawn appearance. Allows for optional stroke pressure variations and provides methods to draw single or overlapping lines.

start

Starting point coordinates of the line

Type:

np.ndarray

end

Ending point coordinates of the line

Type:

np.ndarray

draw() OpsSet

Draws a hand-drawn-like line with some jitter.

draw_single_line(opsset: OpsSet, move: bool = False, overlay: bool = False) OpsSet
class handanim.primitives.lines.LinearPath(points: list[tuple[float, float]], close: bool = False, *args, **kwargs)

Bases: Drawable

A drawable linear path that connects a series of points, with optional closing of the path.

points

A list of (x, y) coordinate points defining the path.

Type:

List[tuple[float, float]]

close

Whether to connect the last point back to the first point. Defaults to False.

Type:

bool, optional

Raises:

ValueError – If fewer than two points are provided.

The path is drawn by creating Line objects between consecutive points, with optional path closure if specified.

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

handanim.primitives.math module

class handanim.primitives.math.Math(tex_expression: str, position: tuple[float, float], font_size: int = 12, font_name: str = 'handanimtype1', *args, **kwargs)

Bases: Drawable

A Drawable class for rendering mathematical expressions using TeX notation.

This class parses a TeX expression and renders individual glyphs using a specified font, supporting custom positioning, scaling, and stroke styling.

tex_expression

The TeX mathematical expression to render

Type:

str

position

The starting position for rendering the expression

Type:

Tuple[float, float]

font_size

The size of the font, defaults to 12

Type:

int, optional

font_name

The name of the font to use for rendering, defaults to “feasibly”

Type:

str

get_glyph_opsset()

Extracts the operations set for a single unicode glyph

draw()

Renders the entire mathematical expression as a set of drawing operations

custom_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]
draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]

Returns the opset for a single glyph of a unicode number

load_font()
standard_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]

handanim.primitives.polygons module

class handanim.primitives.polygons.NGon(center: tuple[float, float], radius: float, n: int, *args, **kwargs)

Bases: Polygon

class handanim.primitives.polygons.Polygon(points: list[tuple[float, float]], *args, **kwargs)

Bases: Drawable

A Polygon class representing a drawable polygon shape.

This class allows creating polygons with a list of points, drawing them with optional stroke and fill styles. It ensures the polygon has at least three points and can render the polygon using a closed linear path with optional filling.

points

A list of (x, y) coordinates defining the polygon vertices.

Type:

List[tuple[float, float]]

Raises:

ValueError – If fewer than three points are provided.

draw() OpsSet

Draw a polygon with the given points

class handanim.primitives.polygons.Rectangle(top_left: tuple[float, float], width: float, height: float, *args, **kwargs)

Bases: Polygon

A Rectangle class representing a rectangular polygon shape.

This class creates a rectangle by specifying its top-left corner coordinates, width, and height. It inherits from the Polygon class and generates the four vertices of the rectangle automatically.

Parameters:
  • top_left (tuple[float, float]) – Coordinates of the top-left corner of the rectangle.

  • width (float) – Width of the rectangle.

  • height (float) – Height of the rectangle.

get_bbox() BoundingBox
class handanim.primitives.polygons.RoundedRectangle(top_left: tuple[float, float], width: float, height: float, border_radius: float = 0.1, *args, **kwargs)

Bases: Drawable

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_bbox() BoundingBox
class handanim.primitives.polygons.RoundedSquare(top_left: tuple[float, float], side_length: float, border_radius: float = 0.1, *args, **kwargs)

Bases: RoundedRectangle

class handanim.primitives.polygons.Square(top_left: tuple[float, float], side_length: float, *args, **kwargs)

Bases: Rectangle

handanim.primitives.text module

class handanim.primitives.text.CustomPen(glyphSet, scale: float = 0.01)

Bases: BasePen

class handanim.primitives.text.Text(text: str, position: tuple[float, float], font_size: int = 12, *args, **kwargs)

Bases: Drawable

A Drawable text primitive that renders text using font glyphs with customizable styling.

Supports rendering text with random font selection, scaling, and sketch-style variations. Converts text characters into drawing operations (OpsSet) that can be rendered.

text

The text to be rendered

Type:

str

position

Starting position for text rendering

Type:

Tuple[float, float]

font_size

Size of the rendered text. Defaults to 12.

Type:

int, optional

scale_factor

Additional scaling factor. Defaults to 1.0.

Type:

float, optional

get_random_font_choice()

Selects a font for text rendering

get_glyph_strokes(char)

Converts a character into drawing operations

get_glyph_space()

Calculates character and space widths

draw()

Generates the complete set of drawing operations for the text

autofit(bbox: BoundingBox)
draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_glyph_space() tuple[float, float]

Gives the width of the space, or an average width

get_glyph_strokes(char) tuple[OpsSet, float]

Gives the glyph operations as well the width of the char for offsetting purpose

get_random_font_choice() tuple[str, str]

Chooses a random font from the available fonts

wrap(bbox: BoundingBox, line_height_factor: float = 1.5)

Pre-compute line breaks so that no line of text exceeds bbox.width.

Splits self.text on spaces and greedily accumulates words onto the current line until adding the next word would exceed bbox.width, then starts a new line. The text block is anchored at bbox.top_left.

Parameters:
  • bbox – The bounding box to wrap text within.

  • line_height_factor – Multiplier on font_size for the vertical gap between lines. 1.5 gives comfortable spacing; 1.2 is tighter.

handanim.primitives.vector_svg module

Vector SVG - authored by Hamd Waseem (https://github.com/hamdivazim/)

A drawable class that accepts an SVG document and renders it as a Drawable as close to the original SVG as possible.

class handanim.primitives.vector_svg.VectorSVG(svg_doc, position: tuple[float, float] = (0, 0), *args, **kwargs)

Bases: Drawable

A drawable class that accepts an SVG document and renders it as a Drawable as close to the original SVG as possible.

Note

This feature was contributed by Hamd Waseem (https://github.com/hamdivazim).

svg_doc

The parsed SVG document object from svgelements.

position

The base (x, y) offset for the SVG.

Type:

tuple[float, float]

draw() OpsSet

Parse SVG elements and convert them into a set of drawing operations

classmethod from_svg_file(svg_file_path: str, *args, **kwargs) VectorSVG

Create a VectorSVG instance from a file path

classmethod from_svg_string(svg_string: str, *args, **kwargs) VectorSVG

Create a VectorSVG instance from an SVG string

Module contents

class handanim.primitives.Arrow(start_point: tuple[float, float], end_point: tuple[float, float], arrow_head_type: str = '->', arrow_head_size: float = 10.0, arrow_head_angle: float = 45.0, *args, **kwargs)

Bases: Drawable

draw()

Provides the list of operations to be performed to draw this particular drawable object on the canvas

class handanim.primitives.Circle(center: tuple[float, float], radius: float, *args, **kwargs)

Bases: Ellipse

A specialized Ellipse where the x and y radii are equal, creating a perfect circle.

Parameters:
  • center (tuple[float, float]) – The center coordinates of the circle.

  • radius (float) – The radius of the circle.

class handanim.primitives.Curve(points: list[tuple[float, float]], *args, **kwargs)

Bases: Drawable

A class representing a curve that can be drawn with a sketchy, hand-drawn style.

Allows creating curves with multiple points, supporting various drawing techniques including single line, quadratic, and more complex multi-point curves with randomization to simulate hand-drawn appearance.

points

List of points defining the curve’s shape.

Type:

List[np.ndarray]

draw() OpsSet

Draw the curve

draw_single_curve(opsset: OpsSet, points: list[ndarray] | None = None, close_point: tuple[float, float] | ndarray | None = None) OpsSet

Draws a single human style sketchy curve

draw_single_curve_with_randomization(opsset: OpsSet, points: list[ndarray] | None = None, offset: float = 1.0) OpsSet

Draw a single human style sketchy curve with random derivations

class handanim.primitives.CurvedArrow(points: list[tuple[float, float]], arrow_head_type: str = '->', arrow_head_size: float = 10.0, arrow_head_angle: float = 45.0, *args, **kwargs)

Bases: Drawable

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

class handanim.primitives.Ellipse(center: tuple[float, float], width: float, height: float, *args, **kwargs)

Bases: Drawable

A drawable ellipse primitive with sketchy rendering capabilities.

Supports customizable center, width, height, and sketch-style rendering with optional multi-stroke and roughness effects. Allows for generating ellipses with randomized point generation and stroke variations.

center

The center point of the ellipse

Type:

np.ndarray

width

The width of the ellipse

Type:

float

height

The height of the ellipse

Type:

float

draw() OpsSet

Draw a sketchy version of an ellipse

draw_ellipse_border(opsset: OpsSet) tuple[list, OpsSet]
class handanim.primitives.Eraser(objects_to_erase: list[Drawable], drawable_cache: DrawableCache, *args, **kwargs)

Bases: Drawable

A Drawable representing an eraser that can remove specified drawable objects.

objects_to_erase

The list of drawable objects to be erased.

Type:

List[Drawable]

drawable_cache

Cache used for calculating bounding box of objects to erase.

Type:

DrawableCache

The draw method generates a zigzag motion over the bounding box of the objects to be erased, using an expanded pen width to create a pastel blend erasing effect.

draw() OpsSet

Calculates the zigzag motion of the eraser

class handanim.primitives.Flowchart(nodes: list[DrawableGroup], connectors: list[FlowchartConnector], **kwargs)

Bases: DrawableGroup

A complete flowchart assembled from FlowchartNode, FlowchartDiamond, and FlowchartConnector primitives.

Prefer constructing via Flowchart.from_dict(spec) rather than directly.

classmethod from_dict(spec: dict[str, Any], **kwargs) Flowchart

Build a Flowchart from a declarative spec dict.

Expected format:

{
    "nodes": [
        {
            "id": "start",
            "type": "node",        # "node" (default) or "diamond"
            "label": "Start",
            "position": [100, 50],
            "size": [100, 40],     # optional
            "font_size": 12,       # optional
        },
        ...
    ],
    "edges": [
        {
            "from": "start",
            "to": "decision",
            "from_side": "bottom",  # optional, default "bottom"
            "to_side": "top",       # optional, default "top"
            "label": "Yes",         # optional edge label
        },
        ...
    ],
}

Additional keys in each node or edge dict are forwarded as keyword arguments to the underlying primitive (e.g. stroke_style, fill_style).

class handanim.primitives.FlowchartConnector(from_node: FlowchartNode | FlowchartDiamond, to_node: FlowchartNode | FlowchartDiamond, from_side: str = 'bottom', to_side: str = 'top', label: str | None = None, label_font_size: int = 10, arrow_head_type: str = '->', arrow_head_size: float = 10.0, arrow_head_angle: float = 45.0, *args, **kwargs)

Bases: Drawable

An auto-routed arrow between two flowchart nodes.

Computes an elbow route from from_node.get_anchor(from_side) to to_node.get_anchor(to_side) at draw time so that moving a node automatically updates the connector without re-construction.

For straight lines (same axis, opposing sides, perfectly aligned), a single Arrow is drawn. Otherwise an L-shaped elbow is used: the connector exits from_node in the from_side direction, turns once at the midpoint, then arrives at to_node from the to_side direction.

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

class handanim.primitives.FlowchartDiamond(label: str, position: tuple[float, float], size: tuple[float, float] = (100.0, 60.0), font_size: int = 12, stroke_style: ~handanim.core.styles.StrokeStyle = <handanim.core.styles.StrokeStyle object>, sketch_style: ~handanim.core.styles.SketchStyle = <handanim.core.styles.SketchStyle object>, fill_style: ~handanim.core.styles.FillStyle | None = None, **kwargs)

Bases: DrawableGroup

A flowchart decision node: a diamond polygon with a centered Text label.

position is the center. size = (width, height) of the diamond’s bounding box.

get_anchor(side: str = 'center') tuple[float, float]
get_bbox() BoundingBox
class handanim.primitives.FlowchartNode(label: str, position: tuple[float, float], size: tuple[float, float] = (100.0, 50.0), font_size: int = 12, stroke_style: ~handanim.core.styles.StrokeStyle = <handanim.core.styles.StrokeStyle object>, sketch_style: ~handanim.core.styles.SketchStyle = <handanim.core.styles.SketchStyle object>, fill_style: ~handanim.core.styles.FillStyle | None = None, **kwargs)

Bases: DrawableGroup

A flowchart process node: a Rectangle with a centered Text label.

position is the center of the node in world coordinates.

get_anchor(side: str = 'center') tuple[float, float]
get_bbox() BoundingBox
class handanim.primitives.Line(start: tuple[float, float] | ndarray, end: tuple[float, float] | ndarray, *args, **kwargs)

Bases: Drawable

A drawable line primitive that generates hand-drawn style lines with randomized jitter and bowing effects.

Supports customizable stroke and sketch styles, with options for line curvature, roughness, and multiple line passes to create a hand-drawn appearance. Allows for optional stroke pressure variations and provides methods to draw single or overlapping lines.

start

Starting point coordinates of the line

Type:

np.ndarray

end

Ending point coordinates of the line

Type:

np.ndarray

draw() OpsSet

Draws a hand-drawn-like line with some jitter.

draw_single_line(opsset: OpsSet, move: bool = False, overlay: bool = False) OpsSet
class handanim.primitives.LinearPath(points: list[tuple[float, float]], close: bool = False, *args, **kwargs)

Bases: Drawable

A drawable linear path that connects a series of points, with optional closing of the path.

points

A list of (x, y) coordinate points defining the path.

Type:

List[tuple[float, float]]

close

Whether to connect the last point back to the first point. Defaults to False.

Type:

bool, optional

Raises:

ValueError – If fewer than two points are provided.

The path is drawn by creating Line objects between consecutive points, with optional path closure if specified.

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

class handanim.primitives.Math(tex_expression: str, position: tuple[float, float], font_size: int = 12, font_name: str = 'handanimtype1', *args, **kwargs)

Bases: Drawable

A Drawable class for rendering mathematical expressions using TeX notation.

This class parses a TeX expression and renders individual glyphs using a specified font, supporting custom positioning, scaling, and stroke styling.

tex_expression

The TeX mathematical expression to render

Type:

str

position

The starting position for rendering the expression

Type:

Tuple[float, float]

font_size

The size of the font, defaults to 12

Type:

int, optional

font_name

The name of the font to use for rendering, defaults to “feasibly”

Type:

str

get_glyph_opsset()

Extracts the operations set for a single unicode glyph

draw()

Renders the entire mathematical expression as a set of drawing operations

custom_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]
draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]

Returns the opset for a single glyph of a unicode number

load_font()
standard_glyph_opsset(unicode: int, font_size: int) tuple[OpsSet, float, float]
class handanim.primitives.NGon(center: tuple[float, float], radius: float, n: int, *args, **kwargs)

Bases: Polygon

class handanim.primitives.Polygon(points: list[tuple[float, float]], *args, **kwargs)

Bases: Drawable

A Polygon class representing a drawable polygon shape.

This class allows creating polygons with a list of points, drawing them with optional stroke and fill styles. It ensures the polygon has at least three points and can render the polygon using a closed linear path with optional filling.

points

A list of (x, y) coordinates defining the polygon vertices.

Type:

List[tuple[float, float]]

Raises:

ValueError – If fewer than three points are provided.

draw() OpsSet

Draw a polygon with the given points

class handanim.primitives.RasterImage(image_path: str, position: tuple[float, float] = (0, 0), width: float | None = None, height: float | None = None, opacity: float = 1.0, **kwargs)

Bases: Drawable

A drawable that places a raster image (PNG, JPEG, etc.) into the scene.

The image is positioned in world coordinates. If only one of width/height is given, the other is computed to preserve the aspect ratio. If neither is given, the image’s pixel dimensions are used as world-coordinate size.

Parameters:
  • image_path – Path to the image file.

  • position – Top-left corner in world coordinates (x, y).

  • width – Display width in world coordinates.

  • height – Display height in world coordinates.

  • opacity – Initial opacity (0.0 transparent, 1.0 opaque).

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

class handanim.primitives.Rectangle(top_left: tuple[float, float], width: float, height: float, *args, **kwargs)

Bases: Polygon

A Rectangle class representing a rectangular polygon shape.

This class creates a rectangle by specifying its top-left corner coordinates, width, and height. It inherits from the Polygon class and generates the four vertices of the rectangle automatically.

Parameters:
  • top_left (tuple[float, float]) – Coordinates of the top-left corner of the rectangle.

  • width (float) – Width of the rectangle.

  • height (float) – Height of the rectangle.

get_bbox() BoundingBox
class handanim.primitives.RoundedRectangle(top_left: tuple[float, float], width: float, height: float, border_radius: float = 0.1, *args, **kwargs)

Bases: Drawable

draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_bbox() BoundingBox
class handanim.primitives.RoundedSquare(top_left: tuple[float, float], side_length: float, border_radius: float = 0.1, *args, **kwargs)

Bases: RoundedRectangle

class handanim.primitives.Square(top_left: tuple[float, float], side_length: float, *args, **kwargs)

Bases: Rectangle

class handanim.primitives.Table(top_left: tuple[float, float], n_rows: int, n_cols: int, cell_width: float, cell_height: float, data: list[list[str]] | None = None, headers: list[str] | None = None, cell_font_size: int = 12, header_font_size: int = 14, stroke_style: ~handanim.core.styles.StrokeStyle = <handanim.core.styles.StrokeStyle object>, sketch_style: ~handanim.core.styles.SketchStyle = <handanim.core.styles.SketchStyle object>, fill_style: ~handanim.core.styles.FillStyle | None = None, header_fill_style: ~handanim.core.styles.FillStyle | None = None, header_stroke_style: ~handanim.core.styles.StrokeStyle | None = None, **kwargs)

Bases: DrawableGroup

A grid of Rectangle + Text cells with optional header-row styling.

Each cell is a DrawableGroup([rect, text]) stored in self.cells[row][col]. Row groups (self.row_groups[r]) contain the leaf rect/text drawables for all cells in that row — they are kept flat (no nested DrawableGroups) so that group-level scene animations apply correctly.

The Table itself is a flat parallel DrawableGroup of all leaf drawables, so scene.add(event, table) animates every cell simultaneously.

Parameters:
  • top_left – (x, y) world coordinates of the table’s top-left corner.

  • n_rows – Total rows, including the header row if headers is provided.

  • n_cols – Number of columns.

  • cell_width – Width of each cell in world units.

  • cell_height – Height of each cell in world units.

  • data – 2-D list of cell strings, indexed [row][col]. Rows with a header start at data[0] = row 1 of the grid. Missing entries default to “”.

  • headers – Column header strings for row 0. If provided, row 0 uses header_stroke_style / header_fill_style instead of the defaults.

  • cell_font_size – Font size for data cells.

  • header_font_size – Font size for header cells.

  • stroke_style – Stroke style for data cells.

  • sketch_style – Sketch style shared by all cells.

  • fill_style – Fill style for data cells (None = no fill).

  • header_stroke_style – Override stroke style for header cells.

  • header_fill_style – Override fill style for header cells.

animate_by_cell(anim_class: type, start_time: float = 0.0, total_duration: float = 1.0, **anim_kwargs) TableRevealEvent

Build a staggered cell-reveal animation in row-major order.

Each cell gets an equal slice of total_duration. Both the rect and the text inside a cell animate together (the cell’s DrawableGroup is the target).

Parameters:
  • anim_class – Any AnimationEvent subclass (e.g. SketchAnimation).

  • start_time – When the first cell’s animation begins, in seconds.

  • total_duration – Total wall-clock span covering all cells.

  • **anim_kwargs – Forwarded to each anim_class constructor.

Returns:

TableRevealEvent whose .add_to_scene(scene) registers all pairs.

animate_by_row(anim_class: type, start_time: float = 0.0, total_duration: float = 1.0, **anim_kwargs) TableRevealEvent

Build a staggered row-reveal animation.

Each row gets an equal slice of total_duration, starting after the previous row’s slice begins. All cells in a row animate in parallel.

Parameters:
  • anim_class – Any AnimationEvent subclass (e.g. SketchAnimation).

  • start_time – When the first row’s animation begins, in seconds.

  • total_duration – Total wall-clock span covering all rows.

  • **anim_kwargs – Forwarded to each anim_class constructor.

Returns:

TableRevealEvent whose .add_to_scene(scene) registers all pairs.

get_bbox() BoundingBox
class handanim.primitives.TableRevealEvent(pairs: list[tuple[Any, DrawableGroup]])

Bases: CompositeAnimationEvent

A CompositeAnimationEvent that pairs each sub-event with its target drawable.

Returned by Table.animate_by_row() and Table.animate_by_cell(). Because Scene.add() always requires an explicit drawable, callers must unpack these pairs themselves — use add_to_scene() as a one-liner convenience.

pairs

List of (AnimationEvent, DrawableGroup) in reveal order.

Usage:

reveal = table.animate_by_row(SketchAnimation, start_time=0, total_duration=3)
reveal.add_to_scene(scene)

# or inspect and filter manually:
for event, drawable in reveal.pairs:
    scene.add(event, drawable)
add_to_scene(scene: Any) None
class handanim.primitives.Text(text: str, position: tuple[float, float], font_size: int = 12, *args, **kwargs)

Bases: Drawable

A Drawable text primitive that renders text using font glyphs with customizable styling.

Supports rendering text with random font selection, scaling, and sketch-style variations. Converts text characters into drawing operations (OpsSet) that can be rendered.

text

The text to be rendered

Type:

str

position

Starting position for text rendering

Type:

Tuple[float, float]

font_size

Size of the rendered text. Defaults to 12.

Type:

int, optional

scale_factor

Additional scaling factor. Defaults to 1.0.

Type:

float, optional

get_random_font_choice()

Selects a font for text rendering

get_glyph_strokes(char)

Converts a character into drawing operations

get_glyph_space()

Calculates character and space widths

draw()

Generates the complete set of drawing operations for the text

autofit(bbox: BoundingBox)
draw() OpsSet

Provides the list of operations to be performed to draw this particular drawable object on the canvas

get_glyph_space() tuple[float, float]

Gives the width of the space, or an average width

get_glyph_strokes(char) tuple[OpsSet, float]

Gives the glyph operations as well the width of the char for offsetting purpose

get_random_font_choice() tuple[str, str]

Chooses a random font from the available fonts

wrap(bbox: BoundingBox, line_height_factor: float = 1.5)

Pre-compute line breaks so that no line of text exceeds bbox.width.

Splits self.text on spaces and greedily accumulates words onto the current line until adding the next word would exceed bbox.width, then starts a new line. The text block is anchored at bbox.top_left.

Parameters:
  • bbox – The bounding box to wrap text within.

  • line_height_factor – Multiplier on font_size for the vertical gap between lines. 1.5 gives comfortable spacing; 1.2 is tighter.

class handanim.primitives.VectorSVG(svg_doc, position: tuple[float, float] = (0, 0), *args, **kwargs)

Bases: Drawable

A drawable class that accepts an SVG document and renders it as a Drawable as close to the original SVG as possible.

Note

This feature was contributed by Hamd Waseem (https://github.com/hamdivazim).

svg_doc

The parsed SVG document object from svgelements.

position

The base (x, y) offset for the SVG.

Type:

tuple[float, float]

draw() OpsSet

Parse SVG elements and convert them into a set of drawing operations

classmethod from_svg_file(svg_file_path: str, *args, **kwargs) VectorSVG

Create a VectorSVG instance from a file path

classmethod from_svg_string(svg_string: str, *args, **kwargs) VectorSVG

Create a VectorSVG instance from an SVG string