# カメラと表示モード — Five SDK

表示モードと視点を切り替え、カメラを操作し、保存したシーンの視点を復元します。

Canonical: https://developer.realsee.ai/ja/docs/five-sdk/camera-and-modes
Source: https://developer.realsee.ai/ja/docs/five-sdk/camera-and-modes.md
Language: ja

シーン読み込み後に表示操作を追加します。

<span id="run-the-example" class="docs-anchor-alias" aria-hidden="true"></span>

## サンプルを実行する

[スターター](https://developer.realsee.ai/ja/docs/five-sdk/quickstart) の **SDK examples** を開き、モード、次の視点、回転、視点保存を試します。各操作の後に実際のシーンを確認してください。

<span id="switch-the-mode" class="docs-anchor-alias" aria-hidden="true"></span>

## 表示モードを切り替える

公開メソッド `changeMode` を使い、結果を await します。この例の値は `Panorama`、`Floorplan`、`Topview` です。変更の完了を確認してから選択状態を更新します。

```ts title="starters/react-five/src/recipes/changeView.ts"
import type { Five, Mode } from "@realsee/five";

export type SceneView = Extract<Mode, "Panorama" | "Floorplan" | "Topview">;

/** Await this from a button handler; show a recoverable error on rejection. */
export async function changeView(five: Five, view: SceneView): Promise<void> {
  await five.changeMode(view, undefined, { duration: 500 });
}

/** Subscribe to the completed mode change, and call the returned cleanup. */
export function watchView(
  five: Five,
  onChange: (view: Mode) => void
): () => void {
  onChange(five.currentMode);
  return five.on("mode.change", (event) => onChange(event.mode));
}
```

Work に必要なモデルやアセットがない場合もあります。現在のシーンを保ち、失敗した操作を表示してください。すべてのシーンで全モードが使えるとは限りません。

<span id="navigate-to-an-actual-viewpoint" class="docs-anchor-alias" aria-hidden="true"></span>

## 実在する視点へ移動する

6.9.2 の実行時確認と同じく、読み込み済み Work の **`active || loadable`** が真の observer を選びます。両方の真は不要です。公開デモには active でも loadable が偽の視点があり、両方を必須にすると全候補が消えます。複数 Work の場合は `panoIndex` と共に `workCode` を保持してください。

```ts title="starters/react-five/src/recipes/navigateScene.ts"
import type { Five, Pano, Pose } from "@realsee/five";

/** Five 6.9.2 accepts active OR explicitly loadable observers, not both flags. */
export function listDestinations(five: Five): Pano[] {
  return five.observers
    .filter((observer) => observer.active || observer.loadable)
    .map((observer) => ({
      workCode: observer.work.workCode,
      panoIndex: observer.panoIndex,
    }));
}

export async function goToDestination(five: Five, pano: Pano): Promise<void> {
  await five.moveToPano(pano, { effect: "fade", duration: 500 });
}

/** Angles use radians. This rotates/zooms without changing the panorama. */
export async function lookAt(
  five: Five,
  pose: Pick<Pose, "longitude" | "latitude" | "fov">
): Promise<void> {
  await five.updateCamera(pose, 500);
}
```

カメラ角度は **ラジアン** です。`updateCamera` は向き、`moveToPano` はパノラマを変えます。結果を予測できるよう別の UI 操作にしてください。

<span id="save-and-restore-a-view" class="docs-anchor-alias" aria-hidden="true"></span>

## 視点を保存して復元する

現在の状態をシリアライズ可能なスナップショットにコピーします。Three.js ベクトルを参照のまま保存しないでください。対応する Work の読み込み後に信頼するスナップショットだけを復元します。

```ts title="starters/react-five/src/recipes/savedViews.ts"
import type { Five, State } from "@realsee/five";
import { Vector3 } from "three";

export type SavedView = Omit<State, "offset"> & {
  offset: [number, number, number];
};

/** The returned value is JSON serializable and does not retain live vectors. */
export function saveView(five: Five): SavedView {
  const state = five.getCurrentState();
  return {
    ...state,
    offset: [state.offset.x, state.offset.y, state.offset.z],
  };
}

/** Restore only a trusted snapshot for the same loaded Work. */
export function restoreView(five: Five, view: SavedView): void {
  if (view.workCode !== five.work.workCode)
    throw new Error("Load the snapshot's Work before restoring its view.");
  five.setState({ ...view, offset: new Vector3(...view.offset) }, true);
}
```

保存した視点は Work 取得の権限を表しません。公開アプリはリソースを別途認可してください。

<span id="check-the-result" class="docs-anchor-alias" aria-hidden="true"></span>

## 結果を確認する

Panorama → Floorplan → Panorama を切り替えます。視点を保存し、移動して復元し、位置と向きが一致するか確認します。モードの拒否とカメラ移動の成功は別々に報告してください。

次は [イベントと座標](https://developer.realsee.ai/ja/docs/five-sdk/events-and-coordinates) へ進みます。

