本システムは、Three.js と OffscreenCanvas を活用して、WEBGL空間にHTML/CSSを動的にレンダリングするコンポーネント「ContentDisplay」を提供します。 このクラスは、SVG_TEMPLATE を基盤に、OffscreenCanvas 上でHTML構文を描画し、その描画結果を THREE.js の Mesh として3Dシーンに配置します。 これは、WEBGL空間にCSSやHTMLを表示するクラス定義のひな型です。このコードに追加したいHTMLを記載していくことで、 WEBGL上に自由なHTML構文を表示できるようになっています。
ContentDisplay クラスは、HTMLコンテンツを3D空間に表示するためのクラスです。 指定されたサイズのHTMLコンテンツを、OffscreenCanvasを用いて描画し、それをテクスチャとしてThree.jsのMeshオブジェクトに適用します。 また、ユーザーが定義したインタラクティブな領域(InteractiveElement)に対するクリックイベントを検出し、対応するコールバック関数を実行する機能を提供します。
InteractiveElement クラスは、ContentDisplay クラスで表示されるHTMLコンテンツ内のインタラクティブな要素を表すクラスです。 要素の座標、サイズ、およびクリック時に実行されるコールバック関数を保持します。
これらのクラスは、以下の主要な技術的要素から構成されています。
displayOptions) によるジオメトリサイズとメッシュ拡大率の調整_updateClass()、update()) による最新内容の反映attachInteraction()) とインタラクティブ要素のコールバック処理setMeshScale()) 機能
// ContentDisplay クラスのコンストラクタ
// width: 表示するコンテンツの幅
// height: 表示するコンテンツの高さ
// displayOptions: 3Dオブジェクトのサイズや拡大率を指定するオプション
constructor(width = 1920, height = 1080, displayOptions = { planeWidth: 150, scale: 2 })
// SVG テンプレートの生成
// 指定された幅と高さを持つSVG文字列を生成します。
_generateRawSVG()
// OffscreenCanvas 上の更新処理
// SVGを生成し、それをData URLに変換してImageオブジェクトとして読み込みます。
// 読み込みが完了したら、OffscreenCanvasに描画し、Meshのテクスチャを更新します。
_updateClass()
// コンポーネントの開始処理
// アニメーションを開始します。
// _createMeshを呼び出してMeshオブジェクトを作成します。
// updateを呼び出してコンテンツを更新します。
// cameraとdomElementが指定されている場合は、attachInteractionを呼び出してインタラクションを設定します。
// アニメーションコールバックが登録されていない場合は、window.animationCallbacksにupdateメソッドを登録します。
start(camera, domElement)
// THREE.js Mesh の作成
// OffscreenCanvasをテクスチャとして使用するMeshオブジェクトを作成します。
// テクスチャのフィルタリング設定を行います。
// displayOptionsで指定されたplaneWidthとアスペクト比から、PlaneGeometryのサイズを決定します。
// MeshBasicMaterialを使用して、テクスチャ、両面表示、透明度、不透明度を設定します。
// Meshの位置を原点に設定します。
// displayOptionsで指定されたscaleを適用して、Meshのサイズを調整します。
_createMesh()
// Mesh の取得
// 作成したMeshオブジェクトを返します。
getMesh()
// 更新処理
// _updateClassを呼び出してコンテンツを更新します。
update()
// インタラクションの設定
// cameraとdomElementを設定します。
// interactiveConfig配列を空に初期化します(現状、この配列は使用されていません)。
// updateInteractiveElementsを呼び出して、インタラクティブな要素を更新します。
// 既存のクリックイベントハンドラがあれば削除します。
// 新しいクリックイベントハンドラをdomElementにアタッチします。
// クリックされた位置を3D空間内の座標に変換します。
// Raycasterを使用して、クリックされた位置にあるMeshとの交差を判定します。
// 交差がある場合は、交差した点のUV座標からSVG内の座標を計算します。
// interactiveElements配列内の各要素について、クリックされた座標が要素の範囲内にあるかどうかを判定し、範囲内にある場合は要素のコールバック関数を実行します。
attachInteraction(camera, domElement)
// インタラクティブ要素の更新
// _generateRawSVGを呼び出してSVG文字列を生成します。
// 画面外に一時的なdiv要素を作成し、そこにSVGを挿入します。
// interactiveConfig配列内の各要素について、対応するDOM要素をSVG内から検索します。
// 要素が見つかった場合は、その要素の位置とサイズを取得し、InteractiveElementオブジェクトを作成します。
// 要素が見つからない場合は、config.defaultで指定された位置とサイズを使用してInteractiveElementオブジェクトを作成します。
// 作成したInteractiveElementオブジェクトをinteractiveElements配列に追加します。
// 一時的なdiv要素を削除します。
updateInteractiveElements()
// メッシュのスケール変更
// Meshオブジェクトのスケールを設定します。
setMeshScale(x, y, z)
// InteractiveElement クラスのコンストラクタ
// x: 要素の左上の座標
// y: 要素の右上の座標
// width: 要素の幅
// height: 要素の高さ
// callback: 要素がクリックされたときに実行されるコールバック関数
constructor(x, y, width, height, callback)
// 指定座標が領域内に含まれるか判定
// 指定された座標が要素の範囲内にあるかどうかを判定します。
contains(pointX, pointY): boolean
ContentDisplay は、非同期処理によって OffscreenCanvas 上に描かれたHTMLコンテンツを定期的に更新します。 具体的には、`update()`メソッドが定期的に呼び出され、`_updateClass()`メソッドによって最新のHTMLコンテンツが再描画されます。 `_updateClass()`メソッドは、`_generateRawSVG()`メソッドで生成されたSVGをData URLに変換し、それを`Image`オブジェクトとして読み込みます。 読み込みが完了したら、`OffscreenCanvas`に描画し、`Mesh`のテクスチャを更新します。
また、`attachInteraction()` メソッドを通じ、DOM上のクリックイベントを Three.js の Raycaster で検出することで、 定義されたインタラクティブ領域内で各コールバックが実行される仕組みを提供します。 `attachInteraction()`メソッドは、`updateInteractiveElements()`メソッドを呼び出して、インタラクティブな要素を更新します。 `updateInteractiveElements()`メソッドは、`_generateRawSVG()`メソッドで生成されたSVGを一時的な`div`要素に挿入し、 `interactiveConfig`配列内の各要素について、対応するDOM要素をSVG内から検索します。 要素が見つかった場合は、その要素の位置とサイズを取得し、`InteractiveElement`オブジェクトを作成します。 要素が見つからない場合は、`config.default`で指定された位置とサイズを使用して`InteractiveElement`オブジェクトを作成します。 作成した`InteractiveElement`オブジェクトを`interactiveElements`配列に追加します。
クリックイベントが発生すると、`attachInteraction()`メソッドで設定されたクリックイベントハンドラが呼び出されます。 クリックイベントハンドラは、クリックされた位置を3D空間内の座標に変換し、`Raycaster`を使用して、クリックされた位置にある`Mesh`との交差を判定します。 交差がある場合は、交差した点のUV座標からSVG内の座標を計算します。 `interactiveElements`配列内の各要素について、クリックされた座標が要素の範囲内にあるかどうかを判定し、範囲内にある場合は要素のコールバック関数を実行します。
以下は、ContentDisplay および InteractiveElement クラスの概要を示す UML クラス図です。
start() により、ContentDisplay が初期化され、OffscreenCanvas 上の描画内容が THREE.CanvasTexture として Mesh に変換され、3Dシーンに配置されます。update() メソッドが定期的に呼ばれ、最新のHTMLコンテンツが再描画されます。attachInteraction() により、DOM のクリックイベントが Three.js の Raycaster で検出され、インタラクティブ領域のコールバックが実行されます。setMeshScale() を使用して、生成済みメッシュのスケールを動的に変更可能です。