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

ManimWeb API#

Bases: AnyWidget

Run a manim-web <https://github.com/maloyan/manim-web>_ scene in a notebook.

manim-web is a TypeScript/WebGL reimplementation of Manim that renders animations entirely in the browser. This widget is a thin runner: it loads the manim-web engine from a CDN, then executes a blob of JavaScript you supply (the code traitlet). The animation plays inline; Python's only job is to hand over the source and the sizing.

Your JavaScript is run as the body of an async function with the manim-web module namespace (manim), the target DOM element (container), the width / height ints, and the widget model in scope. The recommended entry point is manim-web's own Player, which renders a full playback UI into container — play/pause, a scrub timeline with segment markers, speed control, fullscreen and export::

const player = new manim.Player(container, {
    width, height, autoPlay: true, backgroundColor: manim.WHITE,
});
player.sequence(async (scene) => {
    const circle = new manim.Circle({
        radius: 1.5, color: manim.BLUE, fillOpacity: 1,
    });
    await scene.play(new manim.Create(circle));
});

PlayerOptions extends SceneOptions, so width/height/ backgroundColor work alongside autoPlay and loop. Colours are plain hex strings (manim.BLUE, or "#e94560" directly); set fillOpacity: 1 for solid shapes on a light background.

The code is executed verbatim in the browser, so only pass JavaScript you trust (typically your own).

Examples:

import marimo as mo
from wigglystuff import ManimWeb

scene = '''
    const player = new manim.Player(container, {
        width, height, autoPlay: true, backgroundColor: manim.WHITE,
    });
    player.sequence(async (scene) => {
        const c = new manim.Circle({
            radius: 1.5, color: manim.BLUE, fillOpacity: 1,
        });
        await scene.play(new manim.Create(c));
    });
'''
mo.ui.anywidget(ManimWeb(code=scene, width=800, height=450))

Point at a local file or a URL instead of an inline string — the first argument accepts any of the three forms:

ManimWeb("scenes/intro.js")
ManimWeb("https://example.com/scene.js")

Create a ManimWeb widget.

The scene source is resolved in Python, so the browser always receives plain JavaScript. code (or src) may be any of:

  • an inline JavaScript string,
  • a path to a local .js file, or
  • an http(s):// URL.

URLs and file paths are fetched/read here at construction time; the detection is by value, so ManimWeb("https://.../scene.js") and ManimWeb("const s = new manim.Scene(...)") both do the right thing.

Parameters:

Name Type Description Default
code Optional[str]

Inline JavaScript, a local file path, or an http(s):// URL. Mutually exclusive with src.

None
src Optional[str]

An explicit alias for code (same accepted forms), handy when the intent is "load from here". Mutually exclusive with code.

None
width int

Container width in pixels.

500
height int

Container height in pixels.

300
version str

The manim-web version to load from the CDN.

'0.3.24'
**kwargs Any

Forwarded to anywidget.AnyWidget.

{}

Raises:

Type Description
ValueError

If neither or both of code and src are given.

Source code in wigglystuff/manim_web.py
def __init__(
    self,
    code: Optional[str] = None,
    *,
    src: Optional[str] = None,
    width: int = 500,
    height: int = 300,
    version: str = "0.3.24",
    **kwargs: Any,
) -> None:
    """Create a ManimWeb widget.

    The scene source is resolved in Python, so the browser always receives
    plain JavaScript. ``code`` (or ``src``) may be any of:

    * an inline JavaScript string,
    * a path to a local ``.js`` file, or
    * an ``http(s)://`` URL.

    URLs and file paths are fetched/read here at construction time; the
    detection is by value, so ``ManimWeb("https://.../scene.js")`` and
    ``ManimWeb("const s = new manim.Scene(...)")`` both do the right thing.

    Args:
        code: Inline JavaScript, a local file path, or an ``http(s)://``
            URL. Mutually exclusive with ``src``.
        src: An explicit alias for ``code`` (same accepted forms), handy
            when the intent is "load from here". Mutually exclusive with
            ``code``.
        width: Container width in pixels.
        height: Container height in pixels.
        version: The manim-web version to load from the CDN.
        **kwargs: Forwarded to ``anywidget.AnyWidget``.

    Raises:
        ValueError: If neither or both of ``code`` and ``src`` are given.
    """
    if (code is None) == (src is None):
        raise ValueError("Provide exactly one of `code` or `src`.")

    source = code if code is not None else src
    super().__init__(
        code=self._resolve_source(source),
        width=width,
        height=height,
        version=version,
        **kwargs,
    )

Synced traitlets#

Traitlet Type Notes
code str Resolved scene JavaScript (inline JS, or the contents of a file / URL, fetched in Python), run against the manim-web manim namespace and a container element.
width int Container width in pixels.
height int Container height in pixels.
version str manim-web version loaded from the CDN.
error str Read-back of the latest JS runtime error, or "".