LoginSignup
29
9

ブラウザ間で3Dシーンを同期: localStorageとThree.jsの革新的活用

Last updated at Posted at 2023-12-06

Xでおもしろいアプリケーションを見つけたので紹介します。
https://github.com/bgstaal/multipleWindow3dScene
1.gif

Three.jsとlocalStorageを使って、複数のブラウザウィンドウ間で3Dシーンを同期することで実現しています。
どのようにコードが書かれているか、重要な部分を抜粋して紹介していきます。

3Dシーン
複数の3Dモデルや環境要素(例えば光源、カメラ配置、背景など)を組み合わせた、より包括的な立体的な表示環境のこと

基本的な処理の流れ

  1. ウィンドウの初期化:

    • 新しいウィンドウを作成し、既存のウィンドウと同期させます。
    • 同期は、localStorageに保存された状態情報を共有することで行われます。
  2. 3Dシーンの初期化とレンダリング:

    • 3Dシーンを設定し、レンダリングします。
    • ウィンドウのサイズが変更されると、シーンは自動的に更新されます。
  3. 状態の同期:

    • localStorageを介して、ウィンドウ間で3Dシーンの状態(例えば、カメラの位置やシーンのオブジェクトの配置)が同期されます。

実装の詳細

※「3Dシーンの初期化とレンダリング」の実装についてはThree.jsの知識がほとんどなので省きます。

ウィンドウの初期化

	// initiate current window (add metadata for custom data to store with each window instance)
	init (metaData)
	{
		this.#windows = JSON.parse(localStorage.getItem("windows")) || [];
		this.#count= localStorage.getItem("count") || 0;
		this.#count++;

		this.#id = this.#count;
		let shape = this.getWinShape();
		this.#winData = {id: this.#id, shape: shape, metaData: metaData};
		this.#windows.push(this.#winData);

		localStorage.setItem("count", this.#count);
		this.updateWindowsLocalStorage();
	}
  • ウィンドウリストの読み込み:

    • localStorageからwindowsキーの値を読み込み、JSON形式で解析します。
    • もしwindowsキーが存在しない場合は、空の配列を使用します。
  • ウィンドウカウントの更新:

    • localStorageからcountキーの値を読み込み、カウントを1増やします。
    • このカウントは、新しいウィンドウの一意のIDとして使用されます。
  • ウィンドウデータの設定:

    • 新しいウィンドウデータオブジェクトを作成し、その形状(shape)、ID、およびカスタムメタデータを設定します。
    • この新しいウィンドウデータを#windowsに追加します。
  • localStorageの更新:

    • countキーとwindowsキーの値をlocalStorageに保存します。

この関数によって、各ウィンドウは独自の識別子と状態を持ち、他のウィンドウとの同期が可能になります。

状態の同期

  • LocalStorageの変更を監視:
    • 他のウィンドウでlocalStorageが変更された場合に反応します。
    • localStorageのeventからwindowキーの変更を監視し、新しいウィンドウ情報に基づいて現在の#windowsを更新します。
    • #windowsの変更があった場合、設定されたコールバック関数を実行し、3Dシーンの状態を更新します。
		// event listener for when localStorage is changed from another window
		addEventListener("storage", (event) => 
		{
			if (event.key == "windows")
			{
				let newWindows = JSON.parse(event.newValue);
				let winChange = that.#didWindowsChange(that.#windows, newWindows);

				that.#windows = newWindows;

				if (winChange)
				{
					if (that.#winChangeCallback) that.#winChangeCallback();
				}
			}
		});
  • ウィンドウのクローズイベント処理:
    • 現在のウィンドウが閉じられる前に、そのウィンドウを#windowsから削除し、localStorageの情報を更新します。
		// event listener for when current window is about to ble closed
		window.addEventListener('beforeunload', function (e) 
		{
			let index = that.getWindowIndexFromId(that.#id);

			//remove this window from the list and update local storage
			that.#windows.splice(index, 1);
			that.updateWindowsLocalStorage();
		});

localStorageの値

以下はwindowsキーに保存されたJSONデータの例です。このデータには、各ウィンドウのID、形状(位置とサイズ)、およびカスタムメタデータが含まれます。

[
   {
      "id":20,
      "shape":{
         "x":18,
         "y":43,
         "w":1257,
         "h":675
      },
      "metaData":{
         "foo":"bar"
      }
   },
   {
      "id":21,
      "shape":{
         "x":477,
         "y":168,
         "w":1977,
         "h":1092
      },
      "metaData":{
         "foo":"bar"
      }
   },
   {
      "id":22,
      "shape":{
         "x":64,
         "y":246,
         "w":1819,
         "h":716
      },
      "metaData":{
         "foo":"bar"
      }
   }
]

最後に

あまりwindow間のことを考えてこなかったこともあり、localStorageがwindow間で共有されていることを初めて知りました。
他にもこの技術を使ってアプリケーションを作った方がXなどで投稿していたのでぜひ探してみてください!

PR

HRBrainでは一緒に働く仲間を募集しています!
Advent Calendarを見ていただき、興味を持っていただいた方はぜひ弊社の採用ページをご確認ください!

29
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
9