Skip to main content
Documentation

Load a scene

Parse Work, mount a sized viewer, observe loading, and release its browser resources.

On this page

Use this task when you already have Work data and need to display it safely.

Run the example

Run the starter, then open SDK examples. A real public scene should reach Ready. Resize the browser and check that the canvas stays aligned with its container.

Work describes a scene; it is not a gateway token, a Team VR identifier, or arbitrary metadata. Public JSON and Team API responses must reach parseWork before load.

Mount and dispose

Give the host a visible width and height. Mount the renderer before loading Work. Keep the returned cleanup and call it when leaving this task or replacing the scene.

import type { Five as FiveInstance } from "@realsee/five";

export type MountedScene = {
  five: FiveInstance;
  dispose: () => void;
};

/** Browser only. Give host an explicit height before calling this function. */
export async function mountScene(
  host: HTMLElement,
  rawWork: unknown,
  signal?: AbortSignal
): Promise<MountedScene> {
  const { Five, parseWork } = await import("@realsee/five");
  signal?.throwIfAborted();
  const five = new Five({ imageOptions: { size: 512 } });
  const layer = document.createElement("div");
  layer.style.cssText = "width:100%;height:100%";
  host.append(layer);
  let disposed = false;
  const resize = new ResizeObserver(() => five.refresh());
  const dispose = () => {
    if (disposed) return;
    disposed = true;
    signal?.removeEventListener("abort", dispose);
    resize.disconnect();
    five.dispose();
    layer.remove();
  };
  signal?.addEventListener("abort", dispose, { once: true });
  try {
    five.appendTo(layer);
    resize.observe(layer);
    await five.load(parseWork(rawWork), "initial");
    signal?.throwIfAborted();
    five.refresh();
    return { five, dispose };
  } catch (error) {
    dispose();
    throw error;
  }
}

Pass an AbortSignal when the host belongs to a component or route. Cancellation releases the instance and its own layer; it does not promise that every SDK-owned asset request stops immediately.

Observe the relevant loading stage

A Work-ready event, panorama texture, model load, and refined model represent different stages. Attach listeners before the load you want to observe; unsubscribe when the viewer is disposed.

import type { Five } from "@realsee/five";

export type LoadingFeedback =
  | { stage: "work"; state: "ready" }
  | { stage: "panorama"; state: "loading"; progress: number }
  | { stage: "panorama"; state: "ready" | "error" }
  | { stage: "model"; state: "ready" | "refined" | "error" };

/** Attach before load. Progress describes an asset, not the entire app/API. */
export function watchLoading(
  five: Five,
  onChange: (value: LoadingFeedback) => void
): () => void {
  const stop = [
    five.on("works.ready", () => onChange({ stage: "work", state: "ready" })),
    five.on("pano.texture.progress", ({ progress }) =>
      onChange({ stage: "panorama", state: "loading", progress })
    ),
    five.on("pano.texture.success", () =>
      onChange({ stage: "panorama", state: "ready" })
    ),
    five.on("pano.texture.error", () =>
      onChange({ stage: "panorama", state: "error" })
    ),
    five.on("models.load", () => onChange({ stage: "model", state: "ready" })),
    five.on("models.refined", () =>
      onChange({ stage: "model", state: "refined" })
    ),
    five.on("model.error", () => onChange({ stage: "model", state: "error" })),
  ];
  return () => stop.forEach((unsubscribe) => unsubscribe());
}

A panorama progress value describes that asset. Do not display it as a fabricated percentage for authentication, all scene assets, or the complete app.

Check the result

  • The panorama or model is visible and responds to interaction.
  • The canvas follows its container after resize.
  • Changing route or scene removes the old canvas and listeners.
  • Missing assets show an error; the app does not substitute a synthetic image.

For Team-owned Work, keep authorization on the server. Continue with Camera and modes.