कई सालों से, वेब डेवलपर को वेब पर जटिल और ज़्यादा इंटरैक्टिव विज़ुअल ऐप्लिकेशन बनाते समय, आर्किटेक्चर से जुड़ा मुश्किल फ़ैसला लेना पड़ता है. क्या आपको बेहतर सिमैंटिक सुविधाओं के लिए, DOM पर भरोसा करना चाहिए या ग्राफ़िक्स की बेहतर परफ़ॉर्मेंस के लिए, सीधे <canvas> एलिमेंट पर रेंडर करना चाहिए?
HTML-in-Canvas API के नए एक्सपेरिमेंटल वर्शन के साथ, आपको किसी एक को चुनने की ज़रूरत नहीं है. यह ऑरिजिन ट्रायल में अभी उपलब्ध है. इस एपीआई की मदद से, सीधे तौर पर किसी 2D कैनवस या WebGL/WebGPU टेक्सचर में DOM कॉन्टेंट बनाया जा सकता है. साथ ही, यूज़र इंटरफ़ेस (यूआई) को इंटरैक्टिव और ऐक्सेस किया जा सकता है. इसके अलावा, इसे अपने पसंदीदा ब्राउज़र की सुविधाओं से जोड़ा जा सकता है. एचटीएमएल को लो-लेवल ग्राफ़िक्स प्रोसेसिंग के साथ मिलाकर, ऐसे अनुभव बनाए जा सकते हैं जो पहले मुमकिन नहीं थे.
डॉम बनाम कैनवस
इस नए एपीआई की अहमियत को समझने के लिए, DOM और Canvas, दोनों की तुलना करना ज़रूरी है.
डीओएम, वेब यूज़र इंटरफ़ेस का मुख्य हिस्सा होता है. यह टेक्स्ट लेआउट के लिए, आउट ऑफ़ द बॉक्स समाधान उपलब्ध कराता है. साथ ही, यह रिच इंटरफ़ेस बनाने के लिए, सिमैंटिक तौर पर समझे गए कॉन्टेंट का इस्तेमाल करता है. इससे उपयोगकर्ता, वेब पेजों पर सामान्य कार्रवाइयां आसानी से कर पाते हैं. जैसे, कॉपी करने के लिए टेक्स्ट को हाइलाइट करना या इमेज को सेव करने के लिए उस पर राइट क्लिक करना. DOM, ब्राउज़र की ज़रूरी सुविधाओं के साथ भी इंटिग्रेट होता है: सुलभता टूल, अनुवाद, पेज में ढूंढें, रीडर मोड, एक्सटेंशन, डार्क मोड, ब्राउज़र ज़ूम, और अपने-आप भरने की सुविधा.
दूसरी ओर, Canvas (और WebGL/WebGPU) की मदद से, पिक्सल के ग्रिड को कम लेवल पर ऐक्सेस किया जा सकता है. इससे, ज़्यादा बेहतर 2D और 3D ग्राफ़िक बनाए जा सकते हैं. गेम और Google Docs या Figma जैसे मुश्किल वेब ऐप्लिकेशन को, बेहतर परफ़ॉर्मेंस वाले इस लो-लेवल ऐक्सेस की ज़रूरत होती है. कैनवस, मूल रूप से पिक्सल की एक ग्रिड होती है. इसलिए, रिस्पॉन्सिव टेक्स्ट जैसी सुविधाओं के लिए, कस्टम यूज़र इंटरफ़ेस (यूआई) के जटिल लॉजिक की ज़रूरत होती थी. इससे आपके बंडल का साइज़ काफ़ी बढ़ जाता था. सबसे अहम बात यह है कि जब यूज़र इंटरफ़ेस (यूआई) को स्टैटिक कैनवस पिक्सल ग्रिड में लॉक कर दिया जाता है, तब ब्राउज़र की सभी सुविधाएं काम नहीं करती हैं.
डीओएम को Canvas पर लाने के फ़ायदे
एचटीएमएल-इन-कैनवस एपीआई, दोनों दुनियाओं को जोड़ने वाला पुल है. <canvas> एलिमेंट में एचटीएमएल रखकर और उसके ट्रांसफ़ॉर्म को सिंक करके, यह पक्का किया जाता है कि कॉन्टेंट पूरी तरह से इंटरैक्टिव बना रहे. साथ ही, सभी ब्राउज़र इंटिग्रेशन अपने-आप काम करें.
<canvas> एलिमेंट के अंदर यूज़र इंटरफ़ेस (यूआई) को डीओएम से मैनेज कराने पर, आपको ये सुविधाएं मिलती हैं:
- टेक्स्ट लेआउट और फ़ॉर्मैटिंग: टेक्स्ट लेआउट और फ़ॉर्मैटिंग को आसान बनाया गया है. इसमें सीएसएस स्टाइल लागू किए गए मल्टीलाइन या द्वि-दिशात्मक टेक्स्ट शामिल हैं.
- फ़ॉर्म कंट्रोल: फ़ॉर्म कंट्रोल को बेहतर बनाया गया है और इस्तेमाल करना आसान है. साथ ही, इन्हें अपनी पसंद के मुताबिक बनाने के ज़्यादा विकल्प उपलब्ध हैं.
- टेक्स्ट चुनना, कॉपी/चिपकाना, और राइट क्लिक करना: उपयोगकर्ता, आपके 3D सीन में मौजूद टेक्स्ट को हाइलाइट कर सकते हैं. इसके अलावा, वे कॉन्टेक्स्ट मेन्यू पर राइट क्लिक भी कर सकते हैं.
- सुलभता: कैनवस में रेंडर किया गया कॉन्टेंट, सुलभता ट्री के लिए उपलब्ध होता है. सुलभता सिस्टम, यूज़र इंटरफ़ेस (यूआई) को सामान्य एचटीएमएल की तरह पार्स कर सकते हैं. साथ ही, इसे स्क्रीन रीडर जैसे सिस्टम के लिए उपलब्ध करा सकते हैं.
- पेज पर ढूंढें: उपयोगकर्ता, पेज पर ढूंढें (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 कैनरी 149 या इसके बाद के वर्शन का इस्तेमाल करें. साथ ही, chrome://flags/#canvas-draw-element फ़्लैग चालू करें. अन्य उपयोगकर्ताओं के लिए एपीआई चालू करने के लिए, ऑरिजिन ट्रायल के लिए रजिस्टर करें.
पहला चरण: बुनियादी Canvas सेटअप
सबसे पहले, <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 की तरह ही काम करता है, लेकिन इसमें DOM एलिमेंट को सोर्स के तौर पर इस्तेमाल किया जाता है.
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 }
);
};
तीसरा चरण: सीएसएस ट्रांसफ़ॉर्म को अपडेट करना
अब आपने एलिमेंट को कैनवस में रेंडर कर दिया है. इसलिए, आपको ब्राउज़र को यह बताना होगा कि वह कहां मौजूद है. इससे कैनवस और DOM के लेआउट के बीच, जगह के हिसाब से सिंक होने की प्रोसेस पूरी होती है. यह इसलिए ज़रूरी है, ताकि ब्राउज़र इवेंट ज़ोन को सही तरीके से मैप कर सके. जैसे, उपयोगकर्ता ने कहां क्लिक किया या कहां होवर किया और एलिमेंट कहां रेंडर किया गया.
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 Matrix को DOM Matrix में बदलें.
- एचटीएमएल एलिमेंट को सामान्य करें. एचटीएमएल एलिमेंट का साइज़, पिक्सल में तय किया जाता है. उदाहरण के लिए, 200 पिक्सल चौड़ा. हालांकि, WebGL आम तौर पर ऑब्जेक्ट को "यूनिट स्क्वेयर" के तौर पर मानता है. उदाहरण के लिए, 0 से 1 तक. अगर आपने सामान्य नहीं किया, तो आपका 200 पिक्सल वाला बटन 200 गुना बड़ा दिखेगा.
- कैनवस व्यूपोर्ट पर मैप करें. इस चरण को "रीस्केलिंग" फ़ेज़ कहा जाता है. यह यूनिट-स्पेस के गणित को वापस खींचकर, स्क्रीन पर मौजूद आपके
<canvas>एलिमेंट के असल पिक्सल डाइमेंशन से मैच करता है. यह Y-ऐक्सिस को भी फ़्लिप करता है, क्योंकि WebGL में ऊपर की ओर पॉज़िटिव होता है, लेकिन CSS में नीचे की ओर पॉज़िटिव होता है. - फ़ाइनल ट्रांसफ़ॉर्म का हिसाब लगाएं. मैट्रिक्स को इस क्रम में गुणा करें:
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();
}
}
लाइब्रेरी और फ़्रेमवर्क के साथ काम करने की सुविधा
कुछ लोकप्रिय लाइब्रेरी में, एचटीएमएल-इन-कैनवस सुविधा के लिए पहले से ही सहायता उपलब्ध है.
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, टेक्सचर एपीआई का इस्तेमाल करके, कैनवस में एचटीएमएल को भी सपोर्ट करता है:
// 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 बिलबोर्ड है. इसमें DOM का इस्तेमाल करके, ऐनिमेशन वाली SVG पेंसिल को सीधे WebGL टेक्सचर में रेंडर किया जाता है. इसके लिए, कस्टम ऐनिमेशन लूप की ज़रूरत नहीं होती.
- अपवर्तक ओवरले: यह एक इंटरैक्टिव टाइपोग्राफ़ी लेयर है. इसे हिलते हुए 3D कर्सर ने बिगाड़ दिया है. हालांकि, इसे पूरी तरह से चुना जा सकता है. साथ ही, पेज पर ढूंढें सुविधा का इस्तेमाल करके खोजा जा सकता है.
कम्यूनिटी के बनाए गए डेमो का कलेक्शन देखें. अगर आपको इस कलेक्शन में अपना एचटीएमएल-इन-कैनवस डेमो दिखाना है, तो उसे जोड़ने के लिए पुल का अनुरोध बनाएं.
सीमाएं
एपीआई में कई सुविधाएं उपलब्ध हैं, लेकिन इसकी कुछ सीमाएं हैं:
- क्रॉस-ऑरिजिन कॉन्टेंट: सुरक्षा और निजता से जुड़ी वजहों से, यह एपीआई क्रॉस-ऑरिजिन iframe कॉन्टेंट के साथ काम नहीं करता.
- मुख्य थ्रेड स्क्रोलिंग: एचटीएमएल-इन-कैनवस को JavaScript की मदद से बनाया जाता है. इसका मतलब है कि स्क्रोलिंग और ऐनिमेशन, JavaScript से अलग अपडेट नहीं हो सकते. हालांकि, कैनवस के बाहर ऐसा किया जा सकता है. डेवलपर को इस बात पर ध्यान देना चाहिए कि कैनवस में स्क्रोल करने वाला कॉन्टेंट डालने से परफ़ॉर्मेंस पर क्या असर पड़ता है. इसके अलावा, उन्हें यह भी देखना चाहिए कि पूरे कैनवस को स्क्रोल करने से परफ़ॉर्मेंस पर क्या असर पड़ता है.
सुझाव/राय दें या शिकायत करें
अगर आपने HTML-in-Canvas API का इस्तेमाल किया है, तो हमें इसके बारे में बताएं! ओरिजिन ट्रायल के लिए साइन अप करके, अपनी साइट पर इस सुविधा को चालू किया जा सकता है. इससे हमें एपीआई डिज़ाइन को बेहतर बनाने में मदद मिलेगी. सुझाव/राय देने या शिकायत करने के लिए, समस्या की जानकारी सबमिट करें.
संसाधन
- Three.js में एचटीएमएल-इन-कैनवस की सुविधा
- Three.js डेमो में एचटीएमएल-इन-कैनवस
- PlayCanvas में HTML-in-Canvas की सुविधा: डेवलपर दस्तावेज़
- PlayCanvas डेमो में HTML-in-Canvas
- एचटीएमएल-इन-कैनवस: जानकारी
- Canvas में एचटीएमएल के लिए, एआई कोडिंग टूल के बारे में मॉडर्न वेब गाइडेंस
- कैनवस में एचटीएमएल के लिए Chrome.dev डेमो
- कम्यूनिटी की ओर से, Canvas में एचटीएमएल का इस्तेमाल करने से जुड़े डेमो का बेहतरीन कलेक्शन