Xでおもしろいアプリケーションを見つけたので紹介します。
https://github.com/bgstaal/multipleWindow3dScene
Three.jsとlocalStorageを使って、複数のブラウザウィンドウ間で3Dシーンを同期することで実現しています。
どのようにコードが書かれているか、重要な部分を抜粋して紹介していきます。
3Dシーン
複数の3Dモデルや環境要素(例えば光源、カメラ配置、背景など)を組み合わせた、より包括的な立体的な表示環境のこと
基本的な処理の流れ
-
ウィンドウの初期化:
- 新しいウィンドウを作成し、既存のウィンドウと同期させます。
- 同期は、
localStorage
に保存された状態情報を共有することで行われます。
-
3Dシーンの初期化とレンダリング:
- 3Dシーンを設定し、レンダリングします。
- ウィンドウのサイズが変更されると、シーンは自動的に更新されます。
-
状態の同期:
-
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を見ていただき、興味を持っていただいた方はぜひ弊社の採用ページをご確認ください!