Skip to main content

anythreejs

A Python / Three.js bridge for Jupyter notebooks, built on anywidget.

This comes out of the need to have a lightweight wrapper around Three.js which is easy to maintain and extend, while being compatible with existing codebases using pythreejs.

Installation

pip install anythreejs

Quick Start

from anythreejs import (
    Renderer,
    Scene,
    PerspectiveCamera,
    OrbitControls,
    Mesh,
    BoxGeometry,
    MeshStandardMaterial,
    AmbientLight,
    DirectionalLight,
)

# Create a scene
scene = Scene(
    children=[
        Mesh(
            geometry=BoxGeometry(1, 1, 1),
            material=MeshStandardMaterial(color="#ff0c0cff", roughness=0.4),
        ),
        AmbientLight(intensity=0.4),
        DirectionalLight(position=[5, 5, 5], intensity=1),
    ],
    background="#e5e5faff",
)

camera = PerspectiveCamera(position=[3, 3, 3])
controls = OrbitControls(controlling=camera)

# Display the widget (renderer is the widget)
renderer = Renderer(
    camera=camera,
    scene=scene,
    controls=[controls],
    width=700,
    height=450,
)
renderer

API Overview

anythreejs provides a subset of Three.js objects as Python classes. Currently we only cover the parts used by plopp. We should ideally automatically generate these classes from the Three.js documentation in the future.

Renderer Options

Renderer(
    scene=scene,           # Scene object
    camera=camera,         # Camera object
    controls=[controls],   # Controls list (e.g., OrbitControls)
    width=800,             # Canvas width in pixels
    height=600,            # Canvas height in pixels
    antialias=True,        # Enable antialiasing
    alpha=False,           # Canvas transparency
    enable_picking=True,   # Raycast on click (fills _click_info)
    enable_hover=False,    # Also raycast on mousemove (fills _hover_info);
                           # off by default — costly for large point clouds
)

Sync model

Python-side changes are sent to the browser as small per-object delta messages (binary buffers for array data), so updating one property of a large scene does not re-transfer the scene. Interactive camera movement (orbit/pan/zoom) is synced back: camera.position, camera.rotation, camera.zoom and controls.target reflect the current view, and camera.observe(handler, names=["position"]) fires as the user navigates.

Interaction

Click Events

import anythreejs as p3

renderer = p3.Renderer(camera=camera, scene=scene, controls=[controls])

def handle_click(change):
    info = change.get("new", {})
    if info:
        print(f"Clicked: {info.get('name')} at {info.get('point')}")

renderer.observe(handle_click, names=["_click_info"])
renderer

pythreejs Compatibility

anythreejs tries to be API-compatible with the original pythreejs. CI continuously verifies the drop-in claim by running the unmodified test suites of three pythreejs-based projects — plopp, matplotgl, and McStasScript — against anythreejs through an import alias. For projects that already use pythreejs, you can switch with minimal changes:

# Instead of:
# import pythreejs as p3

# Use:
import anythreejs as p3

Example (pythreejs-style usage)

import anythreejs as p3

# Create camera
camera = p3.PerspectiveCamera(aspect=800/600)
camera.position = [5, 5, 5]

# Create scene
axes = p3.AxesHelper()
scene = p3.Scene(children=[camera, axes], background="#f0f0f0")

# Create controls
controls = p3.OrbitControls(controlling=camera)

# Create renderer (this is the widget)
renderer = p3.Renderer(
    camera=camera,
    scene=scene,
    controls=[controls],
    width=800,
    height=600,
)

# Add objects dynamically
mesh = p3.Mesh(
    geometry=p3.BoxGeometry(1, 1, 1),
    material=p3.MeshStandardMaterial(color="#ff0000"),
)
scene.add(mesh)

# Display
renderer

Development

The browser side (js/widget.js) is bundled together with three.js into src/anythreejs/static/widget.js, so the widget makes no network requests at runtime — it works in air-gapped deployments and offline notebooks. After editing js/widget.js, rebuild the committed bundle:

npm install
npm run build

Run the test suite with uv run pytest tests/. The browser-level tests additionally need uv run playwright install chromium; they load the shipped bundle in headless Chromium with the network disabled and assert on rendered pixels, GPU resource counts, and camera round-trips.

Type stubs for the catalog-generated classes are committed (src/anythreejs/core/*.pyi); regenerate them after changing the catalog:

uv run python scripts/generate_stubs.py

Known limitations

  • One parent per object in the browser. Python lets you add() the same object under two parents, but three.js reparents silently — it renders only under the last parent added (the same constraint the original pythreejs had).
  • ShaderMaterial uniforms must be JSON-serializable — texture-valued uniforms are not supported yet.

Credits

Metadata

Release files for anythreejs 0.3.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for anythreejs 0.3.4
File Size Uploaded
anythreejs-0.3.4.tar.gz 187.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for anythreejs 0.3.4
File Interpreter ABI Platform
anythreejs-0.3.4-py3-none-any.whl Python 3 none any Details

Total release size: 384.8 kB

Release files / anythreejs-0.3.4.tar.gz

Download URL anythreejs-0.3.4.tar.gz
Size 187.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d0c53140bf2ea04ac22c7691f5ff4fbed48cd835df159dd5de8e09ee69688a50
BLAKE2b-256 checksum
How to use checksums
569458f1728c0d82a214257e6fd36b64d6104a9168da0a9506c02a76c286d1bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / anythreejs-0.3.4-py3-none-any.whl

Download URL anythreejs-0.3.4-py3-none-any.whl
Size 197.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7932ee64f74054273a610817c1bda775088d8f3e53de5e695cfcc44abffea31e
BLAKE2b-256 checksum
How to use checksums
2cd01ea56e61ea23975cf5e0b72f77eee6803d685412f2ad5347f92c112f7933
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.3.4 This release

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page