3D सीन में इंटरैक्टिव एचटीएमएल कॉन्टेंट की सुविधा चालू करना

वेब सुविधाएं: कैनवस में एचटीएमएल

HTML-in-Canvas API की मदद से, रीयल डीओएम को सीधे कैनवस एलिमेंट में रेंडर किया जा सकता है. WebGL, WebGPU या Three.js जैसे 3D रेंडरिंग कॉन्टेक्स्ट पर लागू करने के लिए, कैनवस में content="drawable" एट्रिब्यूट और उसके डिसेंडेंट एचटीएमएल एलिमेंट में drawable एट्रिब्यूट जोड़ें. इससे उन एलिमेंट को 3D सीन में आसानी से प्रोजेक्ट किया जा सकता है. सबसे ज़रूरी बात यह है कि एचटीएमएल एलिमेंट, ऐक्टिव डीओएम लेआउट ट्री का हिस्सा बने रहते हैं. इसलिए, वे पूरी तरह से इंटरैक्टिव रहते हैं. इससे उपयोगकर्ता, बटन पर क्लिक कर सकते हैं, टेक्स्ट चुन सकते हैं, और फ़ोकस की स्थितियों को नेटिव तौर पर ट्रिगर कर सकते हैं. इसके लिए, उन्हें जटिल रेकास्टिंग या कस्टम इवेंट हैंडलिंग की ज़रूरत नहीं पड़ती.

इन्हें कैसे लागू करें

WebGL और WebGPU

WebGL या WebGPU का इस्तेमाल करते समय, यह तरीका अपनाएं:

  1. देखें कि ब्राउज़र में HTML-in-Canvas की सुविधा काम करती है या नहीं:

    if ('content' in HTMLCanvasElement.prototype) {
      // Use HTML in Canvas API
    } else {
      // Use fallback strategy
    }
    
  2. <canvas> एचटीएमएल एलिमेंट में content="drawable" एट्रिब्यूट जोड़कर, <canvas> को शुरू करें, ताकि डिसेंडेंट एचटीएमएल एलिमेंट काम कर सकें. अपने एचटीएमएल कॉन्टेंट को <canvas> एलिमेंट के अंदर रखें. साथ ही, ड्रॉ किए जाने वाले हर एलिमेंट में drawable एट्रिब्यूट जोड़ें. drawable वाला एलिमेंट, अपने सबट्री को कैप्चर करता है. हालांकि, यह नेस्ट किए गए उन डिसेंडेंट को कैप्चर नहीं करता जो drawable भी हैं:

    <canvas id="canvas" content="drawable">
      <div id="html-content" drawable></div>
    </canvas>
    
  3. धुंधलेपन से बचने के लिए, अपने कैनवस ग्रिड को डिवाइस के स्केल फ़ैक्टर के हिसाब से स्केल करें:

    const observer = new ResizeObserver(([entry]) => {
      const dpc = entry.devicePixelContentBoxSize;
      canvas.width = dpc
        ? dpc[0].inlineSize
        : Math.round(entry.contentRect.width * window.devicePixelRatio);
      canvas.height = dpc
        ? dpc[0].blockSize
        : Math.round(entry.contentRect.height * window.devicePixelRatio);
    });
    
    const supportsDevicePixelContentBox =
      typeof ResizeObserverEntry !== "undefined" &&
      "devicePixelContentBoxSize" in ResizeObserverEntry.prototype;
    const options = supportsDevicePixelContentBox
      ? { box: "device-pixel-content-box" }
      : {};
    observer.observe(canvas, options);
    
  4. canvas.onpaint इवेंट हैंडलर में, एचटीएमएल कॉन्टेंट को टेक्सचर में रेंडर करें. कैनवस पर पेंट होने के बाद ही किसी एलिमेंट को अपलोड किया जा सकता है: paint इवेंट का अनुरोध करने के लिए, canvas.requestPaint() को कॉल करें.

canvas.captureElementImage(element) से टेक्स्चर का साइज़ तय करें. इसके width और height, कैनवस ग्रिड (बैकिंग स्टोर) पिक्सल में होते हैं. इसलिए, उन्हें Math.ceil() के साथ राउंड अप करें. अगर एलिमेंट में अब तक कोई पेंट रिकॉर्ड नहीं है, तो captureElementImage() गड़बड़ी दिखाता है: requestPaint() को कॉल करें और अगले paint इवेंट पर फिर से कोशिश करें.

// Returns the element's size in canvas grid pixels, or null if the element
// has no paint record yet.
function getElementImageSize(canvas, element) {
  let elementImage;
  try {
    elementImage = canvas.captureElementImage(element);
  } catch (err) {
    canvas.requestPaint(); // No paint record yet: retry on the next paint event.
    return null;
  }
  const width = Math.ceil(elementImage.width);
  const height = Math.ceil(elementImage.height);
  elementImage.close();
  return width > 0 && height > 0 ? { width, height } : null;
}
  • WebGL कॉन्टेक्स्ट में, texImage2D तरीके का इस्तेमाल करके, पहले से ही टेक्सचर बैकिंग तय करें. इस गाइड में दिए गए स्निपेट, WebGL 2 कॉन्टेक्स्ट (canvas.getContext("webgl2")) का इस्तेमाल करते हैं. पिक्सल डेटा के बजाय null के साथ texImage2D() को कॉल करके, टेक्सचर स्टोरेज तय करें. इससे, बिना कोई पिक्सल अपलोड किए, दिए गए साइज़ और फ़ॉर्मैट की जीपीयू मेमोरी रिज़र्व हो जाती है. इन नियमों का पालन करें:
    • captureElementImage() से टेक्स्चर का साइज़ तय करें, जैसा कि ऊपर दिखाया गया है.
    • लेवल 0 को सिर्फ़ पहली बार अपलोड करते समय या साइज़ बदलने पर असाइन करें. ऐसा इसलिए, क्योंकि फिर से असाइन करने पर टेक्सचर हट जाता है. म्यूटेबल स्टोरेज का इस्तेमाल करें: एलिमेंट का साइज़ बदलने पर, इम्यूटेबल texStorage2D() स्टोरेज का साइज़ नहीं बदला जा सकता.
// Binds the texture, and allocates its storage on the first upload, and when
// the element size changes. `state` stores the allocated size.
function allocateElementTexture(gl, texture, state, width, height) {
  gl.bindTexture(gl.TEXTURE_2D, texture);
  if (state.width === width && state.height === height) return;

  gl.texImage2D(
    gl.TEXTURE_2D,
    0,                // Mipmap level
    gl.RGBA8,         // Internal format: 8 bits per RGBA channel
    width,            // Size in canvas grid pixels
    height,
    0,                // Border: must be 0
    gl.RGBA,          // Format and type that match RGBA8
    gl.UNSIGNED_BYTE,
    null              // null reserves GPU memory without uploading pixels
  );
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  state.width = width;
  state.height = height;
}

const texture = gl.createTexture();
const textureState = { width: 0, height: 0 };
  • इसके बाद, WebGL कॉन्टेक्स्ट में, texElementSubImage2D तरीके का इस्तेमाल करके एचटीएमएल कॉन्टेंट को टेक्सचर में रेंडर करें. इन नियमों का पालन करें:
    • कॉन्फ़िगरेशन में { width, height } पास करें. इससे कॉपी, तय किए गए टेक्सचर को भर देती है. भले ही, कैनवस को किसी भी तरह से स्केल किया गया हो.
    • अगर साइज़ बदल गया है, तो टेक्सचर को फिर से असाइन करें, जैसा कि ऊपर दिखाया गया है.
// Uploads the element into the texture. Returns false if the element has no
// paint record yet. In that case, it's uploaded on the next paint event.
function uploadElementWebGL(gl, canvas, texture, element, state) {
  const size = getElementImageSize(canvas, element);
  if (!size) return false;
  const { width, height } = size;

  // Bind the texture, and reallocate it if the size changed (see above).
  allocateElementTexture(gl, texture, state, width, height);
  gl.texElementSubImage2D(gl.TEXTURE_2D, 0, 0, 0, element, { width, height });
  return true;
}

canvas.onpaint = () => {
  try {
    uploadElementWebGL(gl, canvas, texture, uiElement, textureState);
  } catch (err) {
    console.error('texElementSubImage2D copy failed:', err);
  }
};
  • WebGPU के संदर्भ में, drawElementImageToTexture तरीके का इस्तेमाल करें. इन नियमों का पालन करें:
    • COPY_DST और RENDER_ATTACHMENT के इस्तेमाल से टेक्सचर बनाएं. साथ ही, शेडर में सैंपल करने के लिए TEXTURE_BINDING जोड़ें. गलत इस्तेमाल को WebGPU की पुष्टि करने से जुड़ी गड़बड़ी के तौर पर रिपोर्ट किया जाता है, न कि अपवाद के तौर पर.
    • टेक्स्चर का साइज़ size के तौर पर पास करें. size के बिना, बड़े एलिमेंट को टेक्सचर के हिसाब से क्लिप किया जाता है. size की मदद से, एलिमेंट को स्केल करके फ़िट किया जाता है.
    • WebGPU टेक्सचर का साइज़ नहीं बदला जा सकता. एलिमेंट का साइज़ बदलने पर, टेक्सचर को फिर से बनाएं. साथ ही, इसे रेफ़रंस के तौर पर इस्तेमाल करने वाले बाइंड ग्रुप को फिर से बनाएं.
// WebGPU textures can't be resized. Create the texture once, and recreate it
// when the element size changes.
function ensureElementTexture(device, state, width, height) {
  if (state.texture?.width === width && state.texture?.height === height) {
    return state.texture;
  }
  state.texture?.destroy();
  state.texture = device.createTexture({
    size: { width, height },
    format: "rgba8unorm",
    usage:
      GPUTextureUsage.TEXTURE_BINDING |
      GPUTextureUsage.COPY_DST |
      GPUTextureUsage.RENDER_ATTACHMENT,
  });
  return state.texture; // Recreate the bind groups that used the previous texture.
}

const textureState = { texture: null };

canvas.onpaint = () => {
  const size = getElementImageSize(canvas, uiElement);
  if (!size) return;
  const previousTexture = textureState.texture;
  const texture = ensureElementTexture(device, textureState, size.width, size.height);
  if (texture !== previousTexture) {
    // New texture: create, or rebuild, the bind groups that reference it.
  }
  try {
    device.queue.drawElementImageToTexture({ source: uiElement }, { texture, size });
  } catch (err) {
    console.error('drawElementImageToTexture copy failed:', err);
  }
};

सीन को रेंडर करने के लिए requestAnimationFrame लूप का इस्तेमाल करते समय, लूप में canvas.requestPaint() को कॉल करें. इससे यह पक्का किया जा सकेगा कि एचटीएमएल कॉन्टेंट, कैनवस पर रेंडर हो. event.changedElements उन एलिमेंट की सूची दिखाता है जिनकी रेंडरिंग में बदलाव हुआ है. पक्का करें कि टेक्सचर को सिर्फ़ तब फिर से अपलोड किया जाए, जब डिसेंडेंट एचटीएमएल एलिमेंट में कोई अपडेट किया गया हो:

function render() {
  // Request to update the canvas
  canvas.requestPaint();
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

canvas.onpaint = (event) => {
  if (event.changedElements && event.changedElements.length > 0) {
    // Update the texture as shown above
  }
  // Render the scene, and sync the element geometry as shown in step 5
};
  1. एलिमेंट की ज्यामिति को सिंक करें.

DOMMatrix की गिनती करें, जो एलिमेंट के बॉर्डर बॉक्स को सीएसएस पिक्सल में, कैनवस पर सीएसएस पिक्सल में मैप करता है. ब्राउज़र को व्यूपोर्ट ट्रांसफ़ॉर्म का इस्तेमाल करके, 3D कोऑर्डिनेट स्पेस से सीएसएस कोऑर्डिनेट स्पेस में मैप करना होगा. इसके लिए, यह तरीका अपनाएं:

  • एचटीएमएल एलिमेंट को सामान्य बनाएं. एचटीएमएल एलिमेंट का साइज़, पिक्सल में तय किया जाता है. उदाहरण के लिए, 200 पिक्सल चौड़ा. हालांकि, WebGL आम तौर पर ऑब्जेक्ट को "यूनिट स्क्वेयर" के तौर पर ट्रीट करता है. उदाहरण के लिए, -0.5 से 0.5 तक. अगर आपने नॉर्मलाइज़ नहीं किया, तो आपका 200 पिक्सल का बटन 200 गुना बड़ा दिखेगा. यह चरण Y-ऐक्सिस को भी फ़्लिप करता है. ऐसा इसलिए, क्योंकि सीएसएस में, डाउन पॉज़िटिव होता है, लेकिन WebGL में, अप पॉज़िटिव होता है.
  • WebGL एमवीपी मैट्रिक्स को DOM मैट्रिक्स में बदलें.
  • कैनवस व्यूपोर्ट पर मैप करें. यह चरण "री-स्केलिंग" फ़ेज़ है: यह उस यूनिट-स्पेस मैथ को वापस स्ट्रेच करता है, ताकि स्क्रीन पर आपके <canvas> एलिमेंट के सीएसएस पिक्सल डाइमेंशन से मैच किया जा सके. साथ ही, Y-ऐक्सिस को वापस फ़्लिप करता है.
  • फ़ाइनल ट्रांसफ़ॉर्म का हिसाब लगाएं. मैट्रिक्स को इस क्रम में गुणा करें: व्यूपोर्ट * एमवीपी * नॉर्मलाइज़ेशन. इन दोनों को एक फ़ाइनल ट्रांसफ़ॉर्म में जोड़ने से एक "मैप" बनता है. इससे ब्राउज़र को पता चलता है कि एचटीएमएल एलिमेंट को कहां रखना है, ताकि वह 3D ड्रॉइंग के साथ अलाइन हो सके. ब्राउज़र, पर्सपेक्टिव डिवाइड की प्रोसेस को पूरा करता है.

    // Maps the element's border box (CSS pixels) to the canvas (CSS pixels), for a
    // quad that spans -0.5 to 0.5 in model space and is drawn with the `mvp` matrix.
    function computeCanvasTransform(canvas, element, mvp) {
      const width = element.offsetWidth;
      const height = element.offsetHeight;
    
      // 1. Normalize the HTML element (CSS pixels -> WebGL Model Space)
      const toGLModel = new DOMMatrix()
        // Scale pixels to 1 unit, flip Y (as in CSS it points down, and in WebGL it points up)
        .scale(1 / width, -1 / height, 1 / height)
        // Center the origin: (0,0) becomes (-width/2, -height/2) before scaling
        .translate(-width / 2, -height / 2);
    
      // 2. Convert WebGL MVP Matrix to DOM Matrix
      const mvpDOM = new DOMMatrix(Array.from(mvp));
    
      // 3. Map to the canvas viewport, in CSS pixels
      const clipToCanvasViewport = new DOMMatrix()
        // Move center (0,0) to center of canvas
        .translate(canvas.clientWidth / 2, canvas.clientHeight / 2)
        // Scale normalized clip (-1..1) to viewport size, and flip Y back
        .scale(canvas.clientWidth / 2, -canvas.clientHeight / 2, canvas.clientHeight / 2);
    
      // 4. Multiply: (Clip -> Pixels) * (MVP) * (pixels -> unit square)
      return clipToCanvasViewport.multiply(mvpDOM).multiply(toGLModel);
    }
    

इसके बाद, ट्रांसफ़ॉर्म को canvas.updateElementGeometry() में canvasTransform के तौर पर पास करें. इससे एचटीएमएल एलिमेंट, रेंडर किए गए पिक्सल के ठीक ऊपर आ जाता है. इससे यह पक्का होता है कि जब कोई उपयोगकर्ता किसी बटन पर क्लिक करता है या टेक्स्ट चुनता है, तो वह असल एचटीएमएल एलिमेंट पर ही क्लिक करता है. ब्राउज़र, एलिमेंट की सुलभता सीमाओं के लिए भी ट्रांसफ़ॉर्म का इस्तेमाल करता है. उदाहरण के लिए, स्क्रीन रीडर की फ़ोकस रिंग के लिए:

  canvas.updateElementGeometry(targetHTMLElement, {
    canvasTransform: computeCanvasTransform(canvas, targetHTMLElement, htmlElementMVP),
  });

हिट टेस्टिंग को कंट्रोल करने के लिए, इन विकल्पों का इस्तेमाल करें:

  • updateElementGeometry() को कॉल करने पर, एलिमेंट हिट-टेस्टिंग ऑर्डर में सबसे ऊपर चला जाता है. { preserveHitTestOrder: true } को पास करें, ताकि वह अपनी पोज़िशन बनाए रखे.
  • हिट टेस्टिंग से किसी एलिमेंट को हटाने के लिए, canvas.clearElementGeometry(element) को कॉल करें. उदाहरण के लिए, जब उसे छिपाया जाता है.

Three.js

  1. देखें कि ब्राउज़र में HTML-in-Canvas की सुविधा काम करती है या नहीं:

    if ('content' in HTMLCanvasElement.prototype) {
      // Use HTML in Canvas API
    } else {
      // Use fallback strategy
    }
    
  2. एचटीएमएल कॉन्टेंट के लिए कस्टम ज्यामिति और मटीरियल बनाएं.

  3. डीओएम एलिमेंट को THREE.HTMLTexture में पास करें. रेंडरर, एलिमेंट को अपने कैनवस में जोड़ता है और ज़रूरी एट्रिब्यूट सेट करता है:

      material.map = new THREE.HTMLTexture(element);
      mesh = new THREE.Mesh( geometry, material );
      scene.add( mesh );
    
  4. एचटीएमएल एलिमेंट को इंटरैक्टिव बनाने के लिए, मेश को InteractionManager के साथ रजिस्टर करें. यह एलिमेंट को मेश के साथ अलाइन रखता है और एलिमेंट की ज्यामिति को कैनवस के साथ सिंक करता है. इससे क्लिक और टेक्स्ट चुनने की सुविधा, असल एचटीएमएल एलिमेंट पर काम करती है. रेंडर करने से पहले, ऐनिमेशन लूप में interactions.update() को कॉल करें:

  import { InteractionManager } from 'three/addons/interaction/InteractionManager.js';

  const interactions = new InteractionManager();
  interactions.connect( renderer, camera );
  interactions.add( mesh );

  // In the animation loop
  interactions.update();
  renderer.render( scene, camera );

कोड का उदाहरण

WebGL कैनवस

<canvas id="canvas" content="drawable" style="width: 400px; height: 400px;">
  <div id="ui-element" drawable>
    <p>WebGL UI Element</p>
    <button>Action</button>
  </div>
</canvas>

<script>
  const canvas = document.getElementById("canvas");
  const gl = canvas.getContext("webgl2");
  const uiElement = document.getElementById("ui-element");

  // getElementImageSize(), allocateElementTexture(), and uploadElementWebGL()
  // are defined in step 4.
  // computeCanvasTransform() is defined in step 5.

  // Setup WebGL texture...
  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  const textureState = { width: 0, height: 0 };

  canvas.onpaint = () => {
    // 1. Update texture with HTML content
    try {
      uploadElementWebGL(gl, canvas, texture, uiElement, textureState);
    } catch (err) {
      console.error('texElementSubImage2D copy failed:', err);
    }

    // ... Render your 3D scene here, calculating htmlElementMVP matrix ...

    // 2. Sync DOM position, hit testing, and accessibility bounds with 3D scene
    canvas.updateElementGeometry(uiElement, {
      canvasTransform: computeCanvasTransform(canvas, uiElement, htmlElementMVP),
    });
  };
</script>

WebGPU Canvas

<canvas id="canvas" content="drawable" style="width: 400px; height: 400px;">
  <div id="ui-element" drawable>
    <p>WebGPU UI Element</p>
  </div>
</canvas>

<script>
  const canvas = document.getElementById("canvas");
  const context = canvas.getContext("webgpu");
  const uiElement = document.getElementById("ui-element");

  // getElementImageSize() and ensureElementTexture() are defined in step 4.
  // computeCanvasTransform() is defined in step 5.

  // Setup WebGPU...
  // const device = ...
  const textureState = { texture: null };

  canvas.onpaint = () => {
    // 1. Copy HTML content to a texture that matches the element size
    const size = getElementImageSize(canvas, uiElement);
    if (size) {
      const previousTexture = textureState.texture;
      const texture = ensureElementTexture(device, textureState, size.width, size.height);
      if (texture !== previousTexture) {
        // New texture: create, or rebuild, the bind groups that reference it.
      }
      try {
        device.queue.drawElementImageToTexture({ source: uiElement }, { texture, size });
      } catch (err) {
        console.error('drawElementImageToTexture copy failed:', err);
      }
    }

    // ... Render your 3D scene here, calculating htmlElementMVP matrix ...

    // 2. Sync DOM position, hit testing, and accessibility bounds (same matrix math as WebGL)
    canvas.updateElementGeometry(uiElement, {
      canvasTransform: computeCanvasTransform(canvas, uiElement, htmlElementMVP),
    });
  };
</script>

Three.js

// 1. Initialize Three.js camera, scene, renderer, mesh, interactions;

// 2. Ensure HTML-in-Canvas feature support
if (!('content' in HTMLCanvasElement.prototype)) {
  // Use a fallback strategy
}

// 3. Initialize the source HTML DOM element
const element = document.createElement('div');
element.innerHTML = '<h1>Hello World</h1>';

// 4. Create geometry and material
const geometry = new RoundedBoxGeometry( 100, 100, 100, 10, 10 );
const material = new THREE.MeshStandardMaterial( { roughness: 0, metalness: 0.5 } );

// 5. Pass the DOM element into THREE.HTMLTexture
material.map = new THREE.HTMLTexture(element);

mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

// 6. Make the HTML element interactive
interactions = new InteractionManager();
interactions.connect( renderer, camera );
interactions.add( mesh );

// 7. Render Loop
function animate() {
  // Keep the HTML element aligned with the mesh, so it receives input
  interactions.update();
  renderer.render(scene, camera);
}

सबसे सही तरीके

  • ज़रूरी: HTML-in-Canvas API का इस्तेमाल करने से पहले, यह देख लें कि आपका ब्राउज़र इसके साथ काम करता है या नहीं.
  • ज़रूरी: WebGL या WebGPU का इस्तेमाल करते समय, <canvas> एलिमेंट में हमेशा content="drawable" एट्रिब्यूट जोड़ें.
  • ज़रूरी: WebGL या WebGPU का इस्तेमाल करते समय, ड्रॉ किए जाने वाले हर एलिमेंट में drawable एट्रिब्यूट जोड़ें. इसमें कैनवस के डायरेक्ट चाइल्ड एलिमेंट भी शामिल हैं.
  • ज़रूरी: WebGL या WebGPU का इस्तेमाल करते समय, कैनवस पर एचटीएमएल कॉन्टेंट रेंडर करने के लिए, onpaint इवेंट हैंडलर का इस्तेमाल करें.
  • ज़रूरी: WebGL का इस्तेमाल करते समय, टेक्सचर बफ़र को texImage2D() के साथ पहले से तय करें. ऐसा सिर्फ़ एक बार करें (जब इसे शुरू किया जाए या एलिमेंट का साइज़ बदला जाए). टेक्सचर को सिर्फ़ तब फिर से असाइन करें, जब साइज़ में बदलाव हो. साथ ही, TEXTURE_MIN_FILTER को LINEAR पर सेट करें.
  • ज़रूरी: WebGL का इस्तेमाल करते समय, एचटीएमएल कॉन्टेंट को किसी टेक्सचर में रेंडर करने के लिए, texElementSubImage2D तरीके का इस्तेमाल करें. यह टेक्सचर, texImage2D() की मदद से पहले से तय किया गया हो और इसका साइज़ captureElementImage() से हो.
  • ज़रूरी: WebGPU का इस्तेमाल करते समय, कैनवस पर एचटीएमएल कॉन्टेंट रेंडर करने के लिए, drawElementImageToTexture तरीके का इस्तेमाल करें. captureElementImage() से टेक्सचर का साइज़ तय करें और साइज़ बदलने पर ही इसे फिर से बनाएं. COPY_DST और RENDER_ATTACHMENT के इस्तेमाल से टेक्सचर बनाएं. साथ ही, टेक्सचर का साइज़ size के तौर पर पास करें.
  • ज़रूरी: WebGL या WebGPU का इस्तेमाल करते समय, canvas.updateElementGeometry(element, { canvasTransform }) को कॉल करके, एचटीएमएल एलिमेंट की ज्यामिति को रेंडर किए गए कॉन्टेंट के साथ सिंक करें.
  • ज़रूरी: Three.js का इस्तेमाल करते समय, मेश को InteractionManager के साथ रजिस्टर करें. साथ ही, ऐनिमेशन लूप में interactions.update() को कॉल करें, ताकि एचटीएमएल एलिमेंट को इनपुट मिल सके.
  • ज़रूरी: स्क्रीन का साइज़ देखें और कैनवस के साइज़ को अपडेट करें, ताकि वह डिवाइस के पिक्सल से मैच हो सके. उदाहरण के लिए, ResizeObserver का इस्तेमाल करके.
  • कैनवस में क्रॉस-ऑरिजिन कॉन्टेंट को एंबेड न करें, क्योंकि यह काम नहीं करता.
  • ResizeObserver को onpaint इवेंट हैंडलर में शुरू न करें, क्योंकि इससे मेमोरी लीक हो सकती है.

फ़ॉलबैक रणनीतियां

फ़िलहाल, HTML-in-Canvas API सभी मॉडर्न ब्राउज़र के साथ काम नहीं करता. इसलिए, आम तौर पर फ़ॉलबैक रणनीति की ज़रूरत होती है.

हालांकि, इस एपीआई की बेहतर परफ़ॉर्मेंस को देखते हुए, अगर ब्राउज़र पर HTML-in-Canvas काम करता है, तो इसका इस्तेमाल किया जाना चाहिए.

फ़ॉलबैक की रणनीति, इस्तेमाल के उदाहरण पर निर्भर करती है. उदाहरण के लिए, कैनवस में इंटरैक्टिव एचटीएमएल कॉन्टेंट के लिए, अगर HTML-in-Canvas काम नहीं करता है, तो सीएसएस का इस्तेमाल करके एचटीएमएल कॉन्टेंट को कैनवस के सबसे ऊपर रखें.

HTML-in-Canvas polyfill

HTML-in-Canvas API के साथ काम न करने वाले ब्राउज़र में, इस एपीआई की नकल करने के लिए, यहां दी गई polyfill स्क्रिप्ट का इस्तेमाल करें.

  1. लाइब्रेरी को इंस्टॉल या एंबेड करें:

    # Install
    npm install three-html-render
    
    # Embed
    <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>
    
  2. HTML-in-Canvas का अनुवाद करने के लिए, installHtmlInCanvasPolyfill() तरीका इस्तेमाल करें.