Skip to content

Live Demo

This page explains the demo as a working integration blueprint.
If you are integrating Potree and mapprism-2d in one app, demo/index.html is the reference implementation.

Open Live Demo in New Tab


What this demo teaches

The demo shows how to run two renderers in one host layout:

  • Potree in panel-3d
  • MapPrism2D in panel-2d
  • A shared header that controls view mode and active panel
  • Runtime synchronization between 3D and 2D view state

In practical terms, it answers:

  • how to initialize both viewers from one bootstrap script
  • how to hide/show panels without breaking MapLibre sizing
  • how to keep context when users move between 3D and 2D
  • how to ship usable built-in 2D controls (layers, HUD, measurement) on day one

Runtime architecture at a glance

demo/index.html is intentionally monolithic so you can trace the full flow in one file:

  1. Load Potree and related global scripts
  2. Load MapPrism2D as an ES module
  3. Create the dual-panel DOM structure (panel-3d, panel-2d)
  4. Start Potree (window.viewer)
  5. Start MapPrism2D (window.map2d) with sync enabled against Potree
  6. Wire UI state transitions (split/alternating + panel switch)

Think of it as a host app skeleton. You can later split this into framework components, but the integration order should stay similar.


UI state model (the part most teams need)

The demo keeps UI logic simple and explicit:

  • viewMode: "alternate" or "split"
  • activePanel: "3d" or "2d" (only relevant in alternating mode)
  • PANELS metadata object: maps panel ids to labels and switch targets

Two small functions drive almost all behavior:

  • setViewMode(nextMode) applies mode classes and updates header/buttons
  • setActivePanel(next) toggles which panel is visible in alternating mode

Important integration detail: after any panel/mode change, it calls:

  • window.map2d.resize()

This is required because MapLibre must recalculate the canvas when its container visibility/size changes.


Potree bootstrap (3D side)

The demo creates Potree first and exposes it globally:

  • window.viewer = new Potree.Viewer(...)
  • sets FOV, point budget, and GUI options
  • loads point cloud: Piney Dam EPT source
  • calls viewer.fitToScreen(...) after load

Why this matters: MapPrism2D sync receives the Potree viewer reference, so Potree must exist before the 2D map is initialized.


MapPrism2D bootstrap (2D side)

The demo then creates:

  • window.map2d = new MapPrism2D(document.getElementById("panel-2d"), config)

The config is close to real integration defaults:

  • initialView: center + zoom + bearing
  • basemap: "uai"
  • layerPanel: true
  • hud: true
  • tools.measurement.controls: true
  • layers: raster + PMTiles stack

This gives you a production-like starting point where users can immediately inspect layers and measurements without custom UI code.


3D <-> 2D sync wiring

The demo enables continuous sync using:

  • sync.enabled: true
  • sync.potree.viewer: window.viewer
  • sync.potree.throttleMs: 50

That setup keeps both views spatially coherent while users navigate either panel.
If your product does not need continuous coupling, start with transition-time handoff (getView() / setView()) and enable continuous sync later.


Measurement tools and debug instrumentation

The measurement UI is enabled through tools.measurement.controls: true.

The demo also adds a debug helper:

  • window.measureDebug

It wraps measurement method calls and logs drawings after each action. This is useful while integrating custom toolbars or validating keyboard finalize/cancel behavior (Enter / Escape).


How to adapt this demo into your app

Use demo/index.html as your migration checklist:

  1. Keep the same container contract (panel-3d, panel-2d) or equivalent sized regions.
  2. Preserve initialization order: Potree first, then MapPrism2D with Potree reference.
  3. Keep explicit view state (viewMode, activePanel) in your host state store.
  4. Call map2d.resize() whenever panel visibility or layout changes.
  5. Start with built-in controls; replace with custom controls only after behavior is stable.
  6. Replace demo layer URLs with your environment-specific sources.

Local run

bash
npm install
npm run dev:site

Then open /demo/index.html and keep this guide next to demo/index.html while reading the source.