वेब डेवलपर को, वेब पर जटिल और ज़्यादा इंटरैक्टिव विज़ुअल ऐप्लिकेशन बनाते समय, आर्किटेक्चर से जुड़ा मुश्किल फ़ैसला लेना पड़ता है. जैसे, क्या वे ज़्यादा सिमैंटिक सुविधाओं के लिए डीओएम का इस्तेमाल करें या कम लेवल के ग्राफ़िक परफ़ॉर्मेंस के लिए सीधे <canvas> एलिमेंट पर रेंडर करें?
अब आपको ऐसा कोई फ़ैसला लेने की ज़रूरत नहीं है, क्योंकि HTML-in-Canvas API का नया एक्सपेरिमेंटल वर्शन, ऑरिजिन ट्रायल में उपलब्ध है. इस एपीआई की मदद से, डीओएम कॉन्टेंट को सीधे तौर पर 2D कैनवस या WebGL/WebGPU टेक्सचर में बनाया जा सकता है. साथ ही, यूज़र इंटरफ़ेस को इंटरैक्टिव, सुलभ, और अपने पसंदीदा ब्राउज़र की सुविधाओं से जोड़ा जा सकता है. एचटीएमएल को कम लेवल के ग्राफ़िक प्रोसेसिंग के साथ मिलाकर, ऐसे अनुभव बनाए जा सकते हैं जो पहले मुमकिन नहीं थे.
डीओएम बनाम कैनवस
इस नए एपीआई की ताकत को समझने के लिए, डीओएम और कैनवस, दोनों की खूबियों को देखना ज़रूरी है.
डीओएम, वेब यूज़र इंटरफ़ेस का मुख्य हिस्सा है. यह, सिमैंटिक तरीके से समझे गए कॉन्टेंट का इस्तेमाल करके, बेहतर इंटरफ़ेस बनाने के लिए, टेक्स्ट लेआउट के सलूशन उपलब्ध कराता है. इससे उपयोगकर्ता, वेब पेजों पर सामान्य कार्रवाइयां आसानी से कर पाते हैं. जैसे, कॉपी करने के लिए टेक्स्ट को हाइलाइट करना या सेव करने के लिए किसी इमेज पर राइट क्लिक करना. हम अक्सर इन कार्रवाइयों को सामान्य मान लेते हैं. डीओएम, ब्राउज़र की ज़रूरी सुविधाओं के साथ भी इंटिग्रेट होता है. जैसे, सुलभता टूल, अनुवाद, पेज में खोजें, रीडर मोड, एक्सटेंशन, डार्क मोड, ब्राउज़र ज़ूम, और अपने-आप भरने की सुविधा.
दूसरी ओर, कैनवस (और WebGL/WebGPU) की मदद से, ज़्यादा बेहतर 2D और 3D ग्राफ़िक के लिए, पिक्सल के ग्रिड को चलाने के लिए, कम लेवल का ऐक्सेस मिलता है. गेम और जटिल वेब ऐप्लिकेशन (जैसे, Google Docs या Figma) के लिए, परफ़ॉर्म करने वाले कम लेवल के ऐक्सेस की ज़रूरत होती है. कैनवस, असल में पिक्सल का ग्रिड होता है. इसलिए, रिस्पॉन्सिव टेक्स्ट जैसी सुविधाओं के लिए, कस्टम यूज़र इंटरफ़ेस लॉजिक की ज़रूरत होती है. इससे बंडल का साइज़ काफ़ी बढ़ जाता है. अहम बात यह है कि डीओएम में इंटिग्रेट की गई ब्राउज़र की सभी सुविधाएं, तब पूरी तरह से काम करना बंद कर देती हैं, जब यूज़र इंटरफ़ेस, स्टैटिक कैनवस पिक्सल ग्रिड में होता है.
डीओएम को कैनवस में लाने के फ़ायदे
HTML-in-Canvas API, एक ऐसा पुल है जो आपको दोनों दुनिया की बेहतरीन सुविधाएं देता है. <canvas> एलिमेंट में एचटीएमएल रखकर और उसके ट्रांसफ़ॉर्म को सिंक करके, यह पक्का किया जाता है कि कॉन्टेंट पूरी तरह से इंटरेक्टिव बना रहे और ब्राउज़र के सभी इंटिग्रेशन अपने-आप काम करें.
<canvas> एलिमेंट में, यूज़र इंटरफ़ेस को डीओएम से मैनेज कराने पर आपको ये सुविधाएं मिलती हैं:
- टेक्स्ट लेआउट और फ़ॉर्मैटिंग: टेक्स्ट लेआउट और फ़ॉर्मैटिंग को आसान बनाया गया है. इसमें, सीएसएस स्टाइल लागू करने के साथ-साथ, मल्टीलाइन या बिडायरेक्शनल टेक्स्ट भी शामिल है.
- फ़ॉर्म कंट्रोल: बेहतर और आसानी से इस्तेमाल किए जा सकने वाले फ़ॉर्म कंट्रोल. इनमें, पसंद के मुताबिक बनाने के ज़्यादा विकल्प मिलते हैं.
- टेक्स्ट चुनना, कॉपी/पेस्ट करना, और राइट क्लिक करना: उपयोगकर्ता, 3D सीन में टेक्स्ट को हाइलाइट कर सकते हैं या कॉन्टेक्स्ट मेन्यू पर राइट क्लिक कर सकते हैं.
- टेक्स्ट चुनना, कॉपी/पेस्ट करना, और राइट क्लिक करना: उपयोगकर्ता, 3D सीन में टेक्स्ट को हाइलाइट कर सकते हैं या कॉन्टेक्स्ट मेन्यू पर राइट क्लिक कर सकते हैं.
- सुलभता: कैनवस में रेंडर किया गया कॉन्टेंट, सुलभता ट्री में दिखता है. सुलभता सिस्टम, यूज़र इंटरफ़ेस को सामान्य एचटीएमएल की तरह पार्स कर सकते हैं और इसे स्क्रीन रीडर जैसे सिस्टम में दिखा सकते हैं.
- Find-in-page: उपयोगकर्ता, पेज में खोजें (Ctrl/Cmd+F) का इस्तेमाल करके, टेक्स्ट खोज सकते हैं. ब्राउज़र, आपके WebGL टेक्सचर में सीधे तौर पर उसे हाइलाइट करेगा.
- Find-in-page: उपयोगकर्ता, पेज में खोजें (Ctrl/Cmd+F) का इस्तेमाल करके, टेक्स्ट खोज सकते हैं. ब्राउज़र, आपके WebGL टेक्सचर में सीधे तौर पर उसे हाइलाइट करेगा.
- इंडेक्स करने की सुविधा और एआई एजेंट इंटरफ़ेस: वेब क्रॉलर और एआई एजेंट, 2D और 3D सीन में रेंडर किए गए टेक्स्ट को आसानी से इंडेक्स और पढ़ सकते हैं.
- एक्सटेंशन इंटिग्रेशन: ब्राउज़र एक्सटेंशन, सामान्य तरीके से काम करते हैं. उदाहरण के लिए, टेक्स्ट-रिप्लेसमेंट एक्सटेंशन, आपके 3D मेश पर रेंडर किए गए टेक्स्ट को अपने-आप अपडेट कर देगा.
- DevTools इंटिग्रेशन: Chrome DevTools में, WebGL/WebGPU यूज़र इंटरफ़ेस एलिमेंट के लिए, कैनवस कॉन्टेंट की जांच की जा सकती है. इंस्पेक्टर में सीएसएस स्टाइल में बदलाव करें और देखें कि 3D टेक्सचर पर वह तुरंत अपडेट हो गया है!
इस्तेमाल करने के तरीके
इस एपीआई की मदद से, कई डोमेन में बेहतर काम किया जा सकता है:
- कैनवस पर आधारित बड़े ऐप्लिकेशन: Google Docs, Miro या Figma जैसे बड़े वेब ऐप्लिकेशन अब अपने कैनवस-ड्रिवन वर्कस्पेस में, ऐप्लिकेशन यूज़र इंटरफ़ेस के जटिल कॉम्पोनेंट को सामान्य तरीके से रेंडर कर सकते हैं. इससे सुलभता बेहतर होती है और बंडल का साइज़ कम होता है.
- 3D सीन और गेम: मार्केटिंग साइट, इमर्सिव WebXR अनुभव, और वेब गेम अब 3D सीन में पूरी तरह से इंटरैक्टिव वेब यूज़र इंटरफ़ेस रख सकते हैं. जैसे, 3D किताब, जिसमें असल डीओएम टेक्स्ट का इस्तेमाल किया गया है या इन-गेम टर्मिनल, जो कॉपी और पेस्ट करने की सुविधा को सामान्य तरीके से सपोर्ट करता है.
एपीआई का इस्तेमाल कैसे करें
एपीआई का इस्तेमाल तीन चरणों में किया जाता है: कैनवस सेट अप करना, कैनवस में रेंडर करना, और सीएसएस ट्रांसफ़ॉर्म को अपडेट करना, ताकि ब्राउज़र को पता चल सके कि एलिमेंट, स्क्रीन पर कहां मौजूद है.
ज़रूरी शर्तें
HTML-in-Canvas API, Chrome 148 से 150 तक ऑरिजिन ट्रायल में उपलब्ध है. अपनी साइट पर इसे टेस्ट करने के लिए, Chrome Canary 149 या इसके बाद के वर्शन का इस्तेमाल करें. साथ ही, chrome://flags/#canvas-draw-element फ़्लैग को चालू करें. अन्य उपयोगकर्ताओं के लिए एपीआई को चालू करने के लिए, ऑरिजिन ट्रायल के लिए रजिस्टर करें.
पहला चरण: कैनवस का बुनियादी सेटअप
सबसे पहले, अपने <canvas> टैग में layoutsubtree एट्रिब्यूट जोड़ें. इससे ब्राउज़र को कैनवस में नेस्ट किए गए कॉन्टेंट के बारे में पता चलता है. साथ ही, यह कॉन्टेंट को कैनवस में दिखाने और सुलभता ट्री में दिखाने के लिए तैयार करता है.
<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
<div id="form_element">
<label for="name">Name:</label> <input id="name" type="text">
</div>
</canvas>
कैनवस ग्रिड का साइज़ तय करना
रेंडर किए गए कॉन्टेंट के धुंधलेपन से बचने के लिए, पक्का करें कि कैनवस ग्रिड का साइज़, डिवाइस के स्केल फ़ैक्टर के हिसाब से हो.
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);
दूसरा चरण: रेंडर करना
2D कॉन्टेक्स्ट के लिए, drawElementImage तरीके का इस्तेमाल करें. paint इवेंट में ऐसा करें. यह इवेंट तब ट्रिगर होता है, जब एलिमेंट फिर से ड्रॉ होता है. उदाहरण के लिए, टेक्स्ट को हाइलाइट करने या उपयोगकर्ता के इनपुट के दौरान. इंटरैक्टिविटी को चालू रखने के लिए, एलिमेंट के सीएसएस ट्रांसफ़ॉर्म को रिटर्न वैल्यू के साथ अपडेट करना ज़रूरी है.
const ctx = document.getElementById('canvas').getContext('2d');
const form_element = document.getElementById('form_element');
const canvas = document.getElementById('canvas');
canvas.onpaint = () => {
ctx.reset();
// Draw the form element at x:0, y:0
let transform = ctx.drawElementImage(form_element, 0, 0);
// Use the transform returned later on...
};
WebGL के साथ रेंडर करना
WebGL के लिए, texElementImage2D का इस्तेमाल करें. यह texImage2D की तरह ही काम करता है, लेकिन इसमें डीओएम एलिमेंट को सोर्स के तौर पर लिया जाता है.
canvas.onpaint = () => {
if (gl.texElementImage2D) {
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, form_element);
}
};
WebGPU के साथ रेंडर करना
WebGPU, डिवाइस की कतार पर copyElementImageToTexture तरीके का इस्तेमाल करता है. यह copyExternalImageToTexture के जैसा ही होता है:
canvas.onpaint = () => {
root.device.queue.copyElementImageToTexture(
valueElement,
{ texture: targetTexture }
);
};
तीसरा चरण: सीएसएस ट्रांसफ़ॉर्म को अपडेट करना
एलिमेंट को कैनवस में रेंडर करने के बाद, आपको ब्राउज़र को यह बताना होगा कि वह कहां मौजूद है. इससे कैनवस और डीओएम के लेआउट के बीच, स्पेस से जुड़ा सिंक पक्का होता है. यह ज़रूरी है, ताकि ब्राउज़र, इवेंट ज़ोन को सही तरीके से मैप कर सके. जैसे, उपयोगकर्ता कहां क्लिक करता है या माउस घुमाता है. साथ ही, यह भी पता चल सके कि एलिमेंट कहां रेंडर किया गया है.
2D कॉन्टेक्स्ट के मामले में, रेंडरिंग कॉल से मिले ट्रांसफ़ॉर्म को .style.transform property पर लागू करें:
const ctx = document.getElementById('canvas').getContext('2d');
const form_element = document.getElementById('form_element');
const canvas = document.getElementById('canvas');
canvas.onpaint = () => {
ctx.reset();
// Draw the form element at x:0, y:0
let transform = ctx.drawElementImage(form_element, 0, 0);
// Sync the DOM location with the drawn location
form_element.style.transform = transform.toString();
};
WebGL या WebGPU के साथ, स्क्रीन पर किसी एलिमेंट की जगह इस बात पर निर्भर करती है कि शेडर कोड, आउटपुट टेक्सचर का इस्तेमाल कैसे करता है. इसे कैनवस रेंडरिंग कॉन्टेक्स्ट से नहीं निकाला जा सकता. हालांकि, अगर आपका शेडर प्रोग्राम, टेक्सचर को ड्रॉ करने के लिए, सामान्य मॉडल व्यू प्रोजेक्शन का इस्तेमाल करता है, तो element.getElementTransform() के नए सुविधा फ़ंक्शन का इस्तेमाल करके, ऐसा ट्रांसफ़ॉर्म कंप्यूट किया जा सकता है जिसे drawElementImage() से मिली रिटर्न वैल्यू की तरह इस्तेमाल किया जा सकता है. इसके लिए, आपको यह करना होगा:
- WebGL MVP मैट्रिक्स को डीओएम मैट्रिक्स में बदलना.
- एचटीएमएल एलिमेंट को सामान्य बनाना. एचटीएमएल एलिमेंट का साइज़ पिक्सल में होता है. उदाहरण के लिए, 200 पिक्सल चौड़ा. हालांकि, WebGL आम तौर पर ऑब्जेक्ट को "यूनिट स्क्वेयर" के तौर पर लेता है. उदाहरण के लिए, 0 से 1 तक. अगर सामान्य नहीं बनाया जाता है, तो आपका 200 पिक्सल वाला बटन, 200 गुना बड़ा दिखेगा.
- कैनवस व्यूपोर्ट पर मैप करना. यह चरण, "रीस्केलिंग" फ़ेज़ है. इसमें, यूनिट-स्पेस मैथ को स्क्रीन पर मौजूद आपके
<canvas>एलिमेंट के असल पिक्सल डाइमेंशन से मैच करने के लिए स्ट्रेच किया जाता है. यह Y-ऐक्सिस को भी फ़्लिप करता है, क्योंकि WebGL में, ऊपर की ओर पॉज़िटिव होता है, लेकिन सीएसएस में, नीचे की ओर पॉज़िटिव होता है. - फ़ाइनल ट्रांसफ़ॉर्म का हिसाब लगाना. मैट्रिक्स को इस क्रम में गुणा करें:
Viewport * MVP * Normalization.इन्हें एक फ़ाइनल ट्रांसफ़ॉर्म में मिलाकर, एक "मैप" बनता है. इससे ब्राउज़र को पता चलता है कि 3D ड्राइंग के साथ अलाइन करने के लिए, एचटीएमएल एलिमेंट लेयर को कहां रखना चाहिए. - एचटीएमएल एलिमेंट पर ट्रांसफ़ॉर्म लागू करना. इससे एचटीएमएल एलिमेंट लेयर, रेंडर किए गए पिक्सल के ठीक ऊपर आ जाती है. इससे यह पक्का होता है कि जब कोई उपयोगकर्ता किसी बटन पर क्लिक करता है या टेक्स्ट चुनता है, तो वह असल एचटीएमएल एलिमेंट पर क्लिक करता है.
if (canvas.getElementTransform) {
// 1. Convert WebGL MVP Matrix to DOM Matrix
const mvpDOM = new DOMMatrix(Array.from(htmlElementMVP));
// 2. Normalize the HTML element (pixels -> 1x1 unit square)
const width = targetHTMLElement.offsetWidth;
const height = targetHTMLElement.offsetHeight;
const cssToUnitSpace = new DOMMatrix()
.scale(1 / width, -1 / height, 1) // Shrink to unit size and flip Y
.translate(-width / 2, -height / 2); // Center the element
// 3. Map to the canvas viewport
const clipToCanvasViewport = new DOMMatrix()
.translate(canvas.width / 2, canvas.height / 2) // Move origin to center
.scale(canvas.width / 2, -canvas.height / 2, 1); // Stretch to canvas dimensions
// 4. Multiply: (Clip -> Pixels) * (MVP) * (pixels -> unit square)
const screenSpaceTransform = clipToCanvasViewport
.multiply(mvpDOM)
.multiply(cssToUnitSpace);
// 5. Apply to the transform
const computedTransform = canvas.getElementTransform(targetHTMLElement, screenSpaceTransform);
if (computedTransform) {
targetHTMLElement.style.transform = computedTransform.toString();
}
}
लाइब्रेरी और फ़्रेमवर्क का सपोर्ट
कुछ लोकप्रिय लाइब्रेरी में, HTML-in-Canvas सुविधा के लिए पहले से ही सपोर्ट मौजूद है.
Three.js
मैट्रिक्स को मैन्युअल तरीके से अपडेट करना मुश्किल हो सकता है. इसलिए, फ़्रेमवर्क पहले से ही इसका इस्तेमाल कर रहे हैं. Three.js में, एक्सपेरिमेंटल सपोर्ट मौजूद है, जिसमें नए THREE.HTMLTexture का इस्तेमाल किया गया है:
const material = new THREE.MeshBasicMaterial();
material.map = new THREE.HTMLTexture(uiElement); // Pass the DOM element
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
PlayCanvas
PlayCanvas में भी, टेक्सचर एपीआई का इस्तेमाल करके, HTML-in-Canvas की सुविधा मौजूद है:
// Wait for the 'paint' event to set the source
canvas.addEventListener('paint', () => {
htmlTexture.setSource(htmlElement);
}, { once: true });
canvas.requestPaint();
// Keep up to date
canvas.addEventListener('paint', onPaintUpload);
const material = new pc.StandardMaterial();
material.diffuseMap = htmlTexture;
material.update();
डेमो
डेमो आज़माने से पहले, पक्का करें कि आपका एनवायरमेंट सही तरीके से कॉन्फ़िगर किया गया हो.
एपीआई का इस्तेमाल करने के लिए, कई डेमो उपलब्ध हैं. हमें कम्यूनिटी से क्रिएटिव सलूशन मिल रहे हैं. इनमें, अनुवाद की जा सकने वाली 3D किताबों से लेकर, यूज़र इंटरफ़ेस एलिमेंट तक शामिल हैं. ये एलिमेंट, ग्लास शेडर के ज़रिए रिफ़्रैक्ट होते हैं:
- 3D किताब: WebGL में रेंडर की गई 3D किताब, जिसके पेजों के लिए एचटीएमएल लेआउट का इस्तेमाल किया गया है. उपयोगकर्ता, सीएसएस की मदद से फ़ॉन्ट बदल सकते हैं. यह डीओएम पर आधारित है. इसलिए, इसमें पहले से मौजूद अनुवाद की सुविधा तुरंत काम करती है. साथ ही, एआई एजेंट, टेक्स्ट को आसानी से एक्सट्रैक्ट कर सकते हैं.
- इंटरैक्टिव 3D यूज़र इंटरफ़ेस: WebGPU जेली स्लाइडर, जो 3D मॉडल के आधार पर लाइट को रिफ़्रैक्ट करता है. साथ ही, यह सामान्य एचटीएमएल
<input type="range">स्टेप एट्रिब्यूट के हिसाब से काम करता है. - ऐनिमेटेड टेक्सचर: डाइनैमिक 3D बिलबोर्ड, जो WebGL टेक्सचर में सीधे तौर पर डीओएम का इस्तेमाल करके, ऐनिमेटेड एसवीजी पेंसिल को रेंडर करता है. इसके लिए, कस्टम ऐनिमेशन लूप की ज़रूरत नहीं होती.
- रिफ़्रैक्टिव ओवरले: इंटरैक्टिव टाइपोग्राफ़ी लेयर, जो मूविंग 3D कर्सर से डिस्टॉर्ट होती है. हालांकि, इसे पेज में खोजें सुविधा का इस्तेमाल करके, पूरी तरह से चुना और खोजा जा सकता है.
कम्यूनिटी की ओर से बनाए गए डेमो का कलेक्शन देखें. अगर आपको इस कलेक्शन में, HTML-in-Canvas का डेमो शामिल करना है, तो उसे जोड़ने के लिए पुल अनुरोध बनाएं.
सीमाएं
यह एपीआई, कई मामलों में काम का है. हालांकि, इसकी कुछ सीमाएं हैं:
- क्रॉस-ऑरिजिन कॉन्टेंट: सुरक्षा और निजता की वजहों से, एपीआई, क्रॉस-ऑरिजिन iframe कॉन्टेंट के साथ काम नहीं करता.
- मुख्य थ्रेड स्क्रोलिंग: HTML-in-Canvas, JavaScript की मदद से ड्रॉ किया जाता है. इसका मतलब है कि स्क्रोलिंग और ऐनिमेशन, JavaScript से अलग से अपडेट नहीं हो सकते. जैसे, वे कैनवस के बाहर हो सकते हैं. डेवलपर को, स्क्रोलिंग कॉन्टेंट को कैनवस में रखने और पूरे कैनवस को स्क्रोल करने की परफ़ॉर्मेंस के बारे में ध्यान से सोचना चाहिए.
सुझाव/राय दें या शिकायत करें
अगर आप HTML-in-Canvas API के साथ एक्सपेरिमेंट कर रहे हैं, तो हमें अपने अनुभव के बारे में बताएं! ऑरिजिन ट्रायल के लिए साइन अप करके, अपनी साइट पर इस सुविधा को चालू किया जा सकता है. इससे हमें एपीआई डिज़ाइन को बेहतर बनाने में मदद मिलेगी. कोई भी सुझाव/राय या शिकायत देने के लिए, समस्या की शिकायत भी की जा सकती है.
संसाधन
- Three.js में, HTML-in-Canvas के लिए सपोर्ट
- Three.js में, HTML-in-Canvas का डेमो
- PlayCanvas में, HTML-in-Canvas के लिए सपोर्ट: डेवलपर दस्तावेज़
- PlayCanvas में, HTML-in-Canvas का डेमो
- HTML-in-Canvas: जानकारी
- HTML-in-Canvas के लिए, एआई कोडिंग टूल के लिए मॉडर्न वेब गाइडेंस
- Chrome.dev पर, HTML-in-Canvas के डेमो
- कम्यूनिटी की ओर से बनाया गया, HTML-in-Canvas के डेमो का कलेक्शन