🌿
🌿 MidoriPhotoArt.
★★★ midori256の改良。安定版。簡易解説あり。おまけ。参考程度。構造化を見直。整理整頓。より利用しやすいクラスにする。Cnvasタグを表示できるようにする。

static_html_Display.js

`static_html_Display.js`は、HTMLテンプレートを基にCanvasへ描画し、Three.jsのテクスチャとして利用できるモジュールです。 動的・静的コンテンツ両方に対応しており、HTML要素を3D空間内でインタラクティブに操作できます。

主な特徴

利用方法

`static_html_Display.js` の基本的な使い方と、各設定項目の詳細、具体的なサンプルコードを説明します。

  1. テンプレートの編集 (static get template()):

    このメソッド内に記述されたHTMLが、Canvasに描画されるコンテンツの基本レイアウトとなります。 ヘッダー、セクション、フッターなど、自由に要素を配置・カスタマイズできます。 テンプレート内には、後述する画像、動画、Canvasなどのプレースホルダー要素を配置できます。

    
    static get template() {
        return `
            <div id="container">
                <header>
                    <h1>My Website</h1>
                </header>
                <section>
                    <!-- ここにプレースホルダーを配置 -->
                    <div id="imagePlaceholder1" style="width:640px; height:360px;"></div>
                    <div id="videoPlaceholder1" style="width:640px; height:360px;"></div>
                    <div id="canvasPlaceholder1" style="width:800px; height:600px;"></div>
                    <button id="myButton">Click Me</button>
                </section>
                <footer>
                    <p>Copyright 2023</p>
                </footer>
            </div>
        `;
    }
                        
  2. メディア領域 (画像、動画、キャンバス) の設定:

    テンプレート内に配置したプレースホルダー要素 (例: <div id="imagePlaceholder1"></div>) に対応する、 画像、動画、Canvas要素の設定を、imageConfigs, videoConfigs, canvasConfigs 配列に記述します。 プレースホルダー要素の style 属性で指定したサイズ (width, height) は、 default オブジェクト内の同名のプロパティで指定します。

    • 画像の設定 (imageConfigs):
      
      this.imageConfigs = [
        {
          selector: '#imagePlaceholder1',  // テンプレート内の対象要素 (IDで指定)
          default: { width: 640, height: 360 }  // プレースホルダーのサイズ
        }
      ];
                                  
    • 動画の設定 (videoConfigs):
      
      this.videoConfigs = [
        {
          selector: '#videoPlaceholder1',  // テンプレート内の対象要素 (IDで指定)
          url: 'path/to/video.mp4',  // 動画ファイルのURL
          default: { width: 640, height: 360 }, // プレースホルダーのサイズ
          autoplay: true, //自動再生
          loop: true,     //ループ再生
          muted: true,    //ミュート
        }
      ];
                                  
    • キャンバスの設定 (canvasConfigs):
      
      this.canvasConfigs = [
        {
          selector: '#canvasPlaceholder1',  // テンプレート内の対象要素 (IDで指定)
          default: { width: 800, height: 600 }  // プレースホルダーのサイズ
          // ここに、Canvasへの描画処理を記述 (後述)
        }
      ];
                                  

      キャンバスの場合は、setupCanvas メソッドをオーバーライドして、Canvasへの描画処理を記述します。

      
      setupCanvas(canvas, config) {
          if (config.selector === '#canvasPlaceholder1') {
              const ctx = canvas.getContext('2d');
              // ここに、Canvasへの描画処理を記述
              ctx.fillStyle = 'red';
              ctx.fillRect(0, 0, canvas.width, canvas.height);
          }
      }
                                  
  3. インタラクティブな要素の設定:

    ユーザー操作対象の要素(例:ボタン)は、this.interactiveConfig に登録し、 レイアウト情報(位置、サイズ)を設定します。 登録された要素は、initializeUI() メソッド内で初期化され、 クリックやホバーなどのイベントが自動的に監視・通知されます。

    
    this.interactiveConfig = [
      {
        selector: '#myButton',  // 対象となるDOM要素 (テンプレート内のID)
        default: { x: 50, y: 50, width: 100, height: 50 }  // 位置とサイズ
      }
    ];
                        

    initializeUI()内では、各要素に対応する初期化関数(例:_setup_myButton())が呼び出されます。 この関数内で、addEventListener を使ってイベントリスナーを登録するなど、 必要に応じた初期化処理を行います。

    
    initializeUI() {
        super.initializeUI(); // 必ず最初に super.initializeUI() を呼ぶ
        this.interactiveConfig.forEach(config => {
            if (config.selector === '#myButton') {
                this._setup_myButton(config);
            }
        });
    }
    
    _setup_myButton(config) {
        const element = this.liveComponentContainer.querySelector(config.selector);
        element.addEventListener('click', () => {
            // ボタンクリック時の処理
            console.log('Button clicked!');
        });
    }
                        
  4. ライブコンポーネントコンテナ:

    このコンポーネントは常に document.getElementById('liveComponentContainer') 内に生成されます。 描画更新やイベント処理は、このコンテナで一元管理され、最新の状態が維持されます。 liveComponentContainer は、StaticHTMLDisplay クラスのインスタンスが持つプロパティで、 動的に生成・更新されるHTML要素が格納されるコンテナ要素です。

概要

このシステムは、WebGLとHTML/CSSを同一空間内で融合させた先進的なアーキテクチャを採用しています。DOM構造を不可視領域でレンダリングし、その結果を画像処理してWebGLの3D空間にテクスチャとしてマッピングします。 イベント処理は、イベント転送メカニズムを介してテクスチャ画像と非表示DOM要素間で連携します。動画、画像、Canvas要素はそれぞれ非表示領域で処理され、随時キャプチャされた画像が3D空間の指定領域にマッピングされます。

通常、このような異なる技術の統合はCORS(Cross-Origin Resource Sharing)などの問題を引き起こす可能性がありますが、本システムではSVGを活用することで、3D空間とDOM要素の合成を効率的に実現しています。

詳細

  1. 不可視領域でのDOMレンダリング:
    • DOM要素は、ユーザーには見えない領域(`liveComponentContainer`)でレンダリングされます。これは、`StaticHTMLDisplay`クラスによって管理されます。(StaticHTMLDisplay.js参照)
    • これにより、通常のWebページと同様のHTML/CSS/JavaScriptの機能を利用できます。
    • 
      // StaticHTMLDisplay.jsより抜粋 (初期化部分)
      constructor(width, height, renderer, options = {}) {
          // ...
          // liveComponentContainerは、DOM要素を保持するためのコンテナ
          this.liveComponentContainer = document.createElement('div');
          this.liveComponentContainer.style.width = `${width}px`;
          this.liveComponentContainer.style.height = `${height}px`;
          this.liveComponentContainer.style.position = 'absolute';
          this.liveComponentContainer.style.top = '0px';
          this.liveComponentContainer.style.left = '0px';
          // 視覚的には非表示にするが、DOMとしては存在させる
          this.liveComponentContainer.style.visibility = 'hidden';
          // ...
      }
                              
  2. 画像処理とテクスチャマッピング:
    • 不可視領域でレンダリングされたDOMは、SVGを用いて画像(Data URL形式)としてキャプチャされます。(StaticHTMLDisplay.js参照)
    • キャプチャされた画像は、WebGLのテクスチャとして3Dオブジェクトにマッピングされます。
    • これにより、3D空間内にHTML/CSSで表現されたコンテンツを表示できます。
    • 
      // StaticHTMLDisplay.jsより抜粋 (更新処理)
      update() {
          // ...
          if (this.needsUpdate) {
              this.updateTexture(); // テクスチャを更新
          }
          // ...
      }
      
      updateTexture() {
              // DOM要素をSVG文字列に変換
              const svgString = this.createSVGString();
              const img = new Image();
              // SVG文字列をBlobオブジェクトに変換
              const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
              // BlobオブジェクトからData URLを生成
              const url = URL.createObjectURL(svgBlob);
      
              img.onload = () => {
                  this.texture.image = img;
                  this.texture.needsUpdate = true; // Three.jsにテクスチャ更新を通知
                  URL.revokeObjectURL(url); // Data URLを解放
                  this.needsUpdate = false;
              };
              img.src = url; // Data URLを画像ソースに設定
      }
      
                              
  3. イベント転送:
    • 3D空間内のテクスチャに対するユーザーインタラクション(クリック、マウスオーバーなど)は、イベント転送メカニズムによって検出されます。
    • 検出されたイベントは、対応する非表示DOM要素に転送され、そこで処理されます。
    • これにより、3D空間内のコンテンツに対しても、通常のDOM要素と同様のインタラクティブな操作が可能になります。
    • 
      // StaticHTMLDisplay.jsより抜粋(イベント処理)
      handleEvent(event) {
          // ...
          // イベントを複製し、対象のDOM要素にディスパッチ
          const clonedEvent = this.cloneAndDispatchEvent(event, targetElement);
          // ...
      }
                              
  4. 動的コンテンツの処理:
    • 動画、画像、Canvasなどの動的コンテンツは、それぞれ専用の非表示領域で処理されます。
    • これらのコンテンツは定期的にキャプチャされ、3D空間内の対応するテクスチャが更新されます。
    • これにより、3D空間内に動的なコンテンツを表示できます。
  5. SVGによる統合:
    • SVG (Scalable Vector Graphics) は、XMLベースのベクター画像フォーマットであり、HTMLやCSSとの親和性が高いです。
    • 本システムでは、SVGを中間層として利用することで、WebGLとDOMの間のデータ交換や座標変換を効率的に行います。
    • SVGの利用は、CORS問題の回避にも貢献します。
    • 
      // StaticHTMLDisplay.jsより抜粋 (SVG文字列生成)
      createSVGString() {
          // liveComponentContainer内のDOM要素をシリアライズ化
          const serialized = new XMLSerializer().serializeToString(this.liveComponentContainer);
          // SVG要素を生成し、シリアライズ化されたDOMをforeignObject内に配置
          const svgString = `<svg xmlns='http://www.w3.org/2000/svg' width='${this.width}' height='${this.height}'>
              <foreignObject x='0' y='0' width='${this.width}' height='${this.height}'>${serialized}</foreignObject>
          </svg>`;
          return svgString;
      }
                              

ソースコード

static_html_Display.js