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.2.0

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.2.0
File Size Uploaded
anythreejs-0.2.0.tar.gz 185.3 kB Details

Built distribution (wheel)

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

Total release size: 380.0 kB

Release files / anythreejs-0.2.0.tar.gz

Download URL anythreejs-0.2.0.tar.gz
Size 185.3 kB
Tags Source
SHA-256 checksum
How to use checksums
208e2cb8d09f130ac69698f34c663ae4a4efd4c811e0e7954d3cf84b16bf85f6
BLAKE2b-256 checksum
How to use checksums
257dce810c6a4af83dfdb367d3433b7764a1e6dad47ace0a04ab23095524ccd5
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.2.0-py3-none-any.whl

Download URL anythreejs-0.2.0-py3-none-any.whl
Size 194.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f88bf6ace52e505b032778768a9507796f511878a0d64d9e22fb626034466332
BLAKE2b-256 checksum
How to use checksums
2de40f5e81eb438811d8b4a37bcd8e22f2cb6e694450c64cb348e1bac61b0ef3
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

0.3.4

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

This release

0.2.0 This release

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