Skip to main content
2plot.ai

dash-pannellum — 360° panoramas for Dash

Interactive 360° panoramas, virtual tours, multi-resolution tiles and 360° video for Plotly Dash 4.

Built on Pannellum — the plug-in-free WebGL panorama viewer — wrapped as a single Dash component with a real-time imperative API.

PyPI Python Dash License Docs

Documentation · PyPI · Changelog · Discord


This repository is two things at once: the component package (dash_pannellum, published to PyPI) and its documentation site — a markdown-driven Dash app where every example is live, deployed at pannellum.2plot.dev as a 2plot network satellite. The site doubles as the component's test bed.

dash-pannellum — interactive 360° panoramas in a Dash app

Install

pip install dash-pannellum

Python 3.9+ and Dash 4.2+. The component's own bundle ships inside the package; the Pannellum 2.5 viewer (and video.js, for 360° video) load from their CDNs at runtime, with one shared load no matter how many viewers are on the page.

Quick start

import dash
from dash import html
from dash_pannellum import DashPannellum

app = dash.Dash(__name__)

app.layout = html.Div(
    DashPannellum(
        id="panorama",
        tour={
            "default": {"firstScene": "alma"},
            "scenes": {
                "alma": {
                    "type": "equirectangular",
                    "panorama": "https://pannellum.org/images/alma.jpg",
                }
            },
        },
        autoLoad=True,
        width="100%",
        height="500px",
    )
)

if __name__ == "__main__":
    app.run(debug=True)

Viewer modes

Pass exactly one of:

Prop Mode
tour Equirectangular panoramas & multi-scene virtual tours
multiRes Tiled multi-resolution (gigapixel) panoramas
video 360° video via video.js (optional HLS/DASH with useHttpStreaming)

Reading the viewer

pitch, yaw, hfov, currentScene, loaded and lastClickedHotspot update from the viewer — use them as Inputs. View-state updates are throttled to 4/s and change-detected, so idle viewers don't fire callbacks.

Driving the viewer in real time

The camera and the scene are imperative — no teardown, no rebuild, no flash:

Prop What it does
lookAt Write {pitch, yaw, hfov, animated} to pan/zoom the live viewer — smooth enough for joystick steering via set_props
loadScene Switch tour scenes in place
callbackHotspots Clickable hotspots that report their name back to Dash; prop changes diff per-name, so markers can drift in real time and stay clickable mid-flight
panoramaCanvasId Point a tour scene at a <canvas> and redraw it to update the sphere's texture in place (dynamicUpdate keeps it live every frame)
orientation Gyroscope look-around — the device is the camera; orientationSupported / orientationActive report back

Changing the configuration props (tour, multiRes, video, compass, northOffset, …) re-initializes the viewer cleanly, so panoramas can be swapped from a callback.

Documentation

Every page at pannellum.2plot.dev runs its examples live:

Page What it shows
/getting-started Install + first panorama
/components/tours Multi-scene tours, scene-switch hotspots, live camera state
/components/scenes Scene config playground + the lookAt fly-to pattern
/components/hotspots Callback hotspots + coordinate-authoring workflow
/components/multires Tiled gigapixel panoramas
/components/video 360° video + HTTP streaming
/components/arena Joystick-driven 360° arena — tilesets composed into data-URI panoramas
/components/emotes Directed camera motions — shake, knockdown, lunge
/components/gyro Gyroscope steering + a desktop tilt simulator
/api Full prop reference, generated from component metadata

Each page also serves an LLM-ready version at /<page>/llms.txt (its prose plus complete example source), and the site exposes /llms.txt, /sitemap.xml and /robots.txt. SKILLS.md is a skills guide to the package — modes, callback patterns, prop reference and gotchas — written for AI coding assistants (and humans in a hurry).

Development

git clone https://github.com/pip-install-python/dash_pannellum
cd dash_pannellum

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt      # the docs site's dependencies

# markdown2dash pins gunicorn<22, against the CVE-driven gunicorn>=23 floor in
# requirements.txt. pip cannot resolve both, so it installs without its
# dependency set — everything it actually needs is already in the line above.
pip install --no-deps markdown2dash==0.1.2

pip install -e .                     # the component itself, editable

npm install
npm run build                        # webpack bundle + generated Python classes

python run.py                        # the docs site at http://127.0.0.1:8561

npm run build writes into dash_pannellum/ — both the bundle and the generated DashPannellum.py. Both are committed: that is what lets pip install work without Node. After a build, restart run.py — the docs site imports the package you just built, so it is the integration test.

The docs app's backend is pluggable (Dash 4.4+). Select it in .env or the environment:

DASH_BACKEND=fastapi python run.py   # ASGI — what production runs
DASH_BACKEND=flask   python run.py   # WSGI default

Or with Docker: docker compose up (serves on port 8561).

Before opening a PR, run the test suite — it boots the real run.py with zero secrets and checks every registered page, exactly as CI's container job does:

pytest

Repository layout

├── src/lib/                  # React component source
│   ├── components/DashPannellum.react.js
│   └── assets/videojs-pannellum-plugin.js
├── dash_pannellum/           # generated Python package (committed)
├── pyproject.toml            # package metadata (dash>=4.2.0)
├── package.json              # JS build toolchain (webpack 5, babel, react 18)
│
├── run.py                    # documentation app entry point
├── docs/                     # markdown docs + live examples (one folder per page)
├── pages/                    # home + markdown loader
├── components/               # appshell, header, navbar (dash-mantine-components)
├── lib/                      # backend resolver, network wiring, analytics
├── assets/ templates/        # css/js, index.html with SEO/LLM meta
├── scripts/                  # social-card generator, link audit, smoke tests
├── tests/                    # secretless pytest suite (flask/fastapi/quart)
└── vendor/                   # dash-clerk-auth tarball (docs-site auth, not on PyPI)

Adding a docs page means adding a folder under docs/ — a markdown file plus the example.py files it references — with no Python wiring anywhere else.

Publish

npm run build
python -m build              # sdist + wheel from pyproject.toml
twine upload dist/*

Upgrading from 0.0.6

dash-pannellum 0.1.0+ is the modernized revival of the original 0.0.6 component: Dash 4.2+ / React 18, coherent customControls semantics, throttled + change-detected view-state updates, callback hotspots wired through real Pannellum click handlers, deduplicated CDN script loading, pyproject.toml packaging. See CHANGELOG.md for the full history, including everything the real-time releases (0.2.0–0.4.0) added.

Credits

License

MIT — see LICENSE. Built by Pip Install Python.

Release files for dash-pannellum 2.0.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 dash-pannellum 2.0.0
File Size Uploaded
dash_pannellum-2.0.0.tar.gz 68.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dash-pannellum 2.0.0
File Interpreter ABI Platform
dash_pannellum-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 101.8 kB

Release files / dash_pannellum-2.0.0.tar.gz

Download URL dash_pannellum-2.0.0.tar.gz
Size 68.8 kB
Tags Source
SHA-256 checksum
How to use checksums
5731f061255259c467b04a93133b3a9d587ef4daf9ebff02b8af5318a872f6ea
BLAKE2b-256 checksum
How to use checksums
d0307498add1c67d9cbf0013632983abe4fd2f1d9a18a896170d1c47f8c4c1f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.

Transparency log

Release files / dash_pannellum-2.0.0-py3-none-any.whl

Download URL dash_pannellum-2.0.0-py3-none-any.whl
Size 33.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f1ba0e8c5282fe72debc2bdd2026c02576324ccb36fd9b8374fd0b9d8962316e
BLAKE2b-256 checksum
How to use checksums
5a909d32694b1c51b2ac946030fea595932c0610c6a0b8132e96365845c24d23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

0.4.0

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

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