Skip to content
Feeding a clanker? Grab this page as raw .md

CurveEditor API#

Bases: AnyWidget

Chart-space curve editor powered by D3 line interpolators.

Drag knots on an x/y chart and switch among D3's chart-oriented curve factories. Open curves store points in x order so step, monotone, and bump curves behave like normal chart lines instead of freeform paths. Closed curves preserve point order so they can be edited as drawn loops.

Examples:

from wigglystuff import CurveEditor

editor = CurveEditor(curve="catmull_rom", alpha=0.5)
editor

Create a CurveEditor widget.

Parameters:

Name Type Description Default
points Iterable[dict[str, Any]] | None

Initial knots as {"x": float, "y": float} dicts. Open curves store points sorted by x-coordinate. Closed curves preserve point order.

None
curve str

D3 curve name. One of linear, step, step_before, step_after, basis, natural, cardinal, catmull_rom, monotone_x, or bump_x.

'natural'
x_bounds tuple[float, float]

Data-coordinate x bounds.

(0.0, 1.0)
y_bounds tuple[float, float]

Data-coordinate y bounds.

(0.0, 1.0)
width int

SVG width in pixels.

600
height int

SVG height in pixels.

360
tension float

Cardinal spline tension, clamped to [0, 1].

0.0
alpha float

Catmull-Rom alpha, clamped to [0, 1].

0.5
closed bool

Whether to append the first point virtually when rendering.

False
playing bool

Whether playback starts immediately.

False
loop bool

Whether playback wraps from t=1 back to t=0.

False
t float

Initial path progress in [0, 1].

0.0
interval_ms int

Milliseconds between browser playback ticks.

30
duration_ms int

Milliseconds for one full t=0 to t=1 traversal.

12000
sync_throttle_ms int

Minimum milliseconds between playback updates synced to Python.

250
selected_index int

Selected point index, or -1.

-1
**kwargs Any

Forwarded to anywidget.AnyWidget.

{}
Source code in wigglystuff/curve_editor.py
def __init__(
    self,
    points: Iterable[dict[str, Any]] | None = None,
    *,
    curve: str = "natural",
    x_bounds: tuple[float, float] = (0.0, 1.0),
    y_bounds: tuple[float, float] = (0.0, 1.0),
    width: int = 600,
    height: int = 360,
    tension: float = 0.0,
    alpha: float = 0.5,
    closed: bool = False,
    playing: bool = False,
    loop: bool = False,
    t: float = 0.0,
    interval_ms: int = 30,
    duration_ms: int = 12000,
    sync_throttle_ms: int = 250,
    selected_index: int = -1,
    **kwargs: Any,
) -> None:
    """Create a CurveEditor widget.

    Args:
        points: Initial knots as ``{"x": float, "y": float}`` dicts.
            Open curves store points sorted by x-coordinate. Closed curves
            preserve point order.
        curve: D3 curve name. One of ``linear``, ``step``,
            ``step_before``, ``step_after``, ``basis``, ``natural``,
            ``cardinal``, ``catmull_rom``, ``monotone_x``, or ``bump_x``.
        x_bounds: Data-coordinate x bounds.
        y_bounds: Data-coordinate y bounds.
        width: SVG width in pixels.
        height: SVG height in pixels.
        tension: Cardinal spline tension, clamped to ``[0, 1]``.
        alpha: Catmull-Rom alpha, clamped to ``[0, 1]``.
        closed: Whether to append the first point virtually when rendering.
        playing: Whether playback starts immediately.
        loop: Whether playback wraps from ``t=1`` back to ``t=0``.
        t: Initial path progress in ``[0, 1]``.
        interval_ms: Milliseconds between browser playback ticks.
        duration_ms: Milliseconds for one full ``t=0`` to ``t=1`` traversal.
        sync_throttle_ms: Minimum milliseconds between playback updates synced to Python.
        selected_index: Selected point index, or ``-1``.
        **kwargs: Forwarded to ``anywidget.AnyWidget``.
    """
    coerced_points = _coerce_points(points, sort_by_x=not closed)
    initial_t = _clamp01(t)
    initial_x, initial_y = _point_at_t(
        _effective_points(coerced_points, closed), initial_t
    )
    super().__init__(
        closed=closed,
        points=coerced_points,
        x=initial_x,
        y=initial_y,
        t=initial_t,
        curve=curve,
        x_bounds=x_bounds,
        y_bounds=y_bounds,
        width=width,
        height=height,
        tension=tension,
        alpha=alpha,
        playing=playing,
        loop=loop,
        interval_ms=interval_ms,
        duration_ms=duration_ms,
        sync_throttle_ms=sync_throttle_ms,
        selected_index=selected_index,
        **kwargs,
    )
    self.observe(self._refresh_current_point, names=["points", "t", "closed"])
    self.observe(self._sort_points_when_opened, names=["closed"])

current_point #

current_point() -> tuple[float, float]

Return the current path progress point as (x, y).

In Python this is a linear distance approximation through the knots. The browser syncs x and y from the actual rendered D3 SVG path whenever the widget is displayed.

Source code in wigglystuff/curve_editor.py
def current_point(self) -> tuple[float, float]:
    """Return the current path progress point as ``(x, y)``.

    In Python this is a linear distance approximation through the knots.
    The browser syncs ``x`` and ``y`` from the actual rendered D3 SVG path
    whenever the widget is displayed.
    """
    return _point_at_t(_effective_points(self.points, self.closed), self.t)

Synced traitlets#

Traitlet Type Notes
points list[dict] Chart knots as {"x": float, "y": float} in data coordinates. Open curves store points sorted by x-coordinate; closed curves preserve drawing order.
x float Current rendered path x-coordinate at t.
y float Current rendered path y-coordinate at t.
t float Path progress, clamped to [0, 1].
curve str One of linear, step, step_before, step_after, basis, natural, cardinal, catmull_rom, monotone_x, or bump_x.
tension float Cardinal curve tension, clamped to [0, 1].
alpha float Catmull-Rom alpha, clamped to [0, 1].
closed bool Whether to virtually append the first point so the path returns to the start.
playing bool Whether playback is currently advancing t.
loop bool Whether playback wraps from t=1 to t=0.
interval_ms int Milliseconds between browser playback ticks.
duration_ms int Milliseconds for one full t=0 to t=1 traversal.
sync_throttle_ms int Minimum milliseconds between playback updates synced to Python.
selected_index int Selected point index, or -1 when no point is selected.
x_bounds tuple[float, float] Data-coordinate x bounds.
y_bounds tuple[float, float] Data-coordinate y bounds.
width int SVG width in pixels.
height int SVG height in pixels.

Helper methods#

Method Returns Description
current_point() tuple[float, float] Current path progress point. In Python this is a linear knot approximation; the browser syncs from the actual rendered D3 path.