HTML-in-Canvas API অরিজিন ট্রায়াল চালু করা হচ্ছে

Thomas Nattestad
Thomas Nattestad

ওয়েবে জটিল, অত্যন্ত ইন্ট্যার‍্যাক্টিভ ভিজ্যুয়াল অ্যাপ্লিকেশন তৈরি করার সময়, ওয়েব ডেভেলপারদের বহু বছর ধরে কঠিন স্থাপত্য সংক্রান্ত সিদ্ধান্ত নিতে হয়েছে। এর সমৃদ্ধ সিম্যান্টিক ফিচারের জন্য DOM-এর উপর নির্ভর করা উচিত নাকি লো-লেভেল গ্রাফিক্স পারফর্ম্যান্সের জন্য সরাসরি <canvas> এলিমেন্টে রেন্ডার করা উচিত?

নতুন পরীক্ষামূলক HTML-in-Canvas API—যা এখন অরিজিন ট্রায়ালে উপলভ্য—এর সাহায্যে আপনাকে আর বেছে নিতে হবে না। এই API আপনাকে UI ইন্টার‍্যাক্টিভ, অ্যাক্সেসযোগ্য এবং আপনার প্রিয় ব্রাউজার ফিচারের সাথে কানেক্ট করা অবস্থায় সরাসরি 2D ক্যানভাস বা WebGL/WebGPU টেক্সচারে DOM কন্টেন্ট আঁকতে দেয়। লো-লেভেল গ্রাফিক্স প্রসেসিংয়ের সাথে HTML মিলিয়ে আপনি এমন অভিজ্ঞতা তৈরি করতে পারবেন যা আগে সম্ভব ছিল না।

DOM বনাম Canvas

এই নতুন API-এর ক্ষমতা বুঝতে, DOM ও Canvas-এর তুলনামূলক শক্তি সম্পর্কে জানলে সুবিধা হয়।

DOM হল ওয়েব UI-এর মূল ভিত্তি। এটি রিচ ইন্টারফেস তৈরি করতে, শব্দার্থগতভাবে বোঝা কন্টেন্ট ব্যবহার করে, বক্সের বাইরে টেক্সট লেআউট সলিউশন অফার করে। এর ফলে ব্যবহারকারীরা ওয়েবপেজ জুড়ে সাধারণ অপারেশন সহজে করতে পারেন—যেমন, কপি করার জন্য টেক্সট হাইলাইট করা বা ছবি সেভ করার জন্য সেটির উপর মাউস রেখে ডানদিকের বোতামে ক্লিক করা। এছাড়াও, DOM প্রয়োজনীয় ব্রাউজার ফিচারের সাথে ইন্টিগ্রেট করে: অ্যাক্সেসিবিলিটি টুল, অনুবাদ, পৃষ্ঠায় খোঁজা, রিডার মোড, এক্সটেনশন, ডার্ক মোড, ব্রাউজার জুম ও অটোফিল।

অন্যদিকে, ক্যানভাস (এবং WebGL/WebGPU) অত্যন্ত উন্নত 2D ও 3D গ্রাফিক্সের জন্য পিক্সেলের গ্রিড ড্রাইভ করতে, লো-লেভেল অ্যাক্সেস দেয়। গেম ও জটিল ওয়েব অ্যাপের (যেমন, Google Docs বা Figma) ক্ষেত্রে এই পারফর্ম্যান্স-ভিত্তিক, লো-লেভেল অ্যাক্সেস প্রয়োজন। ক্যানভাস মূলত পিক্সেলের একটি গ্রিড হওয়ায়, রেসপন্সিভ টেক্সটের মতো ফিচার কাজ করানোর জন্য জটিল কাস্টম UI লজিক প্রয়োজন হয়, যার ফলে বান্ডেলের সাইজ অনেক বেড়ে যায়। গুরুত্বপূর্ণভাবে, UI যখন স্ট্যাটিক ক্যানভাস পিক্সেল গ্রিডের মধ্যে আটকে যায়, তখন DOM-এ ইন্টিগ্রেট করা সমস্ত শক্তিশালী ব্রাউজার ফিচার সম্পূর্ণভাবে ভেঙে যায়।

Canvas-এ DOM নিয়ে আসার সুবিধা

HTML-in-Canvas API হল সেই ব্রিজ যা আপনাকে দু'টি জগতের সেরা সুবিধা প্রদান করে। <canvas> এলিমেন্টের মধ্যে HTML প্লেস করে এবং এর ট্রান্সফর্ম সিঙ্ক্রোনাইজ করে, আপনি নিশ্চিত করেন যে কন্টেন্টটি সম্পূর্ণ ইন্ট্যার‍্যাক্টিভ থাকে এবং সমস্ত ব্রাউজার ইন্টিগ্রেশন অটোমেটিক কাজ করে।

<canvas> এলিমেন্টের মধ্যে DOM-কে আপনার UI ম্যানেজ করতে দিলে আপনি কী কী সুবিধা পাবেন তা এখানে দেওয়া হল:

  • টেক্সট লেআউট ও ফর্ম্যাটিং: CSS স্টাইল প্রয়োগ করা মাল্টিলাইন বা দ্বিমুখী টেক্সট সহ সরলীকৃত টেক্সট লেআউট ও ফর্ম্যাটিং।
  • ফর্ম কন্ট্রোল: অনেক বেশি কাস্টমাইজেশন বিকল্প সহ ফর্ম কন্ট্রোল যা আরও বেশি এক্সপ্রেসিভ ও সহজে ব্যবহারযোগ্য।
  • টেক্সট বেছে নেওয়া, কপি/পেস্ট করা এবং ডানদিকের বোতামে ক্লিক করা: ব্যবহারকারীরা আপনার 3D দৃশ্যের মধ্যে টেক্সট হাইলাইট করতে বা নেটিভভাবে ডানদিকের বোতামে ক্লিক করে প্রসঙ্গ মেনু দেখতে পারবেন।
  • অ্যাক্সেসিবিলিটি: ক্যানভাসের মধ্যে রেন্ডার করা কন্টেন্ট অ্যাক্সেসিবিলিটি ট্রি-তে এক্সপোজ করা হয়। অ্যাক্সেসিবিলিটি সিস্টেম, সাধারণ HTML-এর মতো UI পার্স করতে পারে এবং স্ক্রিন রিডারের মতো সিস্টেমের কাছে তা প্রকাশ করতে পারে।
  • পৃষ্ঠায় খুঁজুন: ব্যবহারকারীরা টেক্সট সার্চ করতে পৃষ্ঠায় খুঁজুন (Ctrl/Cmd+F) ব্যবহার করতে পারেন এবং ব্রাউজার সরাসরি আপনার WebGL টেক্সচারের মধ্যে এটি হাইলাইট করে।
  • ইনডেক্স করা যায় ও AI এজেন্ট ইন্টারফেস করা যায়: ওয়েব ক্রলার ও AI এজেন্ট আপনার 2D ও 3D সিনের মধ্যে রেন্ডার করা টেক্সটকে স্বচ্ছন্দে ইনডেক্স ও পড়তে পারে।
  • এক্সটেনশন ইন্টিগ্রেশন: ব্রাউজার এক্সটেনশন নেটিভভাবে কাজ করে। যেমন, টেক্সট-রিপ্লেসমেন্ট এক্সটেনশন আপনার 3D মেশে রেন্ডার করা টেক্সট অটোমেটিক আপডেট করে।
  • DevTools ইন্টিগ্রেশন: আপনি Chrome DevTools-এ সরাসরি WebGL/WebGPU UI এলিমেন্ট সহ আপনার ক্যানভাসের কন্টেন্ট চেক করতে পারবেন। ইনস্পেক্টরে CSS স্টাইল পরিবর্তন করুন এবং 3D টেক্সচারে তা সঙ্গে সঙ্গে আপডেট হতে দেখুন!

উচ্চ-স্তরের ব্যবহারিক প্রয়োগ

এই API বিভিন্ন ডোমেন জুড়ে অসাধারণ সম্ভাবনা আনলক করে:

  • ক্যানভাস-ভিত্তিক বড় অ্যাপ্লিকেশন: ভারী ওয়েব অ্যাপগুলি এখন তাদের ক্যানভাস-পরিচালিত ওয়ার্কস্পেসে জটিল অ্যাপ্লিকেশন UI কম্পোনেন্ট নেটিভভাবে রেন্ডার করতে পারে, যা অ্যাক্সেসিবিলিটি উন্নত করে এবং বান্ডেল সাইজ কমিয়ে দেয়।
  • 3D দৃশ্য ও গেম: মার্কেটিং সাইট, ইমার্সিভ WebXR অভিজ্ঞতা ও ওয়েব গেম এখন 3D দৃশ্যে সম্পূর্ণ ইন্ট্যার‍্যাক্ট করা যায় এমন ওয়েব UI প্লেস করতে পারে—যেমন, একটি 3D বই যা আসল DOM টেক্সট ব্যবহার করে অথবা একটি ইন-গেম টার্মিনাল যা নেটিভভাবে কপি ও পেস্ট করার সুবিধা দেয়।

API কীভাবে ব্যবহার করতে হয়

API ব্যবহার করার প্রসেসটি তিনটি ধাপে সম্পন্ন হয়: ক্যানভাস সেট-আপ করা, ক্যানভাসে রেন্ডার করা এবং CSS ট্রান্সফর্ম আপডেট করা যাতে ব্রাউজার বুঝতে পারে যে এলিমেন্টটি স্ক্রিনের কোথায় আছে।

পূর্বশর্ত

Chrome 148 থেকে 150 ভার্সনে HTML-in-Canvas API অরিজিন ট্রায়ালে আছে। আপনার সাইটে এটি পরীক্ষা করে দেখতে, chrome://flags/#canvas-draw-element ফ্ল্যাগ চালু করে Chrome Canary 149 বা তার পরবর্তী যেকোনও ভার্সন ব্যবহার করুন। অন্যান্য ব্যবহারকারীদের জন্য API চালু করতে, অরিজিন ট্রায়ালে রেজিস্টার করুন।

ধাপ ১: প্রাথমিক ক্যানভাস সেট-আপ

প্রথমে, আপনার <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 ইভেন্টের মধ্যে এটি করুন, যা এলিমেন্ট আবার আঁকার সময় ট্রিগার হয়—যেমন, টেক্সট হাইলাইট করা বা ব্যবহারকারীর ইনপুট দেওয়ার সময়। ইন্টার‍্যাক্টিভিটি যাতে কাজ করা চালিয়ে যেতে পারে, তার জন্য রিটার্ন ভ্যালু সহ এলিমেন্টের CSS ট্রান্সফর্ম আপডেট করা অত্যন্ত গুরুত্বপূর্ণ।

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 }
  );
};

ধাপ ৩: CSS ট্রান্সফর্ম আপডেট করা

ক্যানভাসে এলিমেন্ট রেন্ডার করার পরে, এটি কোথায় আছে তা আপনাকে ব্রাউজারকে জানাতে হবে। এটি ক্যানভাস ও 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-এ কনভার্ট করুন।
  • HTML এলিমেন্টকে স্বাভাবিক করুন। HTML এলিমেন্টের সাইজ পিক্সেলে (যেমন, ২০০ পিক্সেল চওড়া) সেট করা হয়। তবে, WebGL সাধারণত অবজেক্টকে "ইউনিট স্কোয়ার" হিসেবে বিবেচনা করে, যেমন, ০ থেকে ১ পর্যন্ত রেঞ্জ। আপনি যদি স্বাভাবিক না করেন, তাহলে আপনার ২০০ পিক্সেল বোতামটি ২০০ গুণ বড় দেখাবে।
  • ক্যানভাসের ভিউপোর্টে ম্যাপ করুন। এই ধাপ হল "রিস্কেল করা" ফেজ। এটি সেই ইউনিট-স্পেস গণিতকে আপনার স্ক্রিনে থাকা <canvas> এলিমেন্টের আসল পিক্সেল ডাইমেনশনের সাথে ম্যাচ করানোর জন্য আবার স্ট্রেচ করে। এটি Y-অক্ষকেও ফ্লিপ করে, কারণ WebGL-এ, উপরের দিকে পজিটিভ, কিন্তু CSS-এ, নিচের দিকে পজিটিভ।
  • ফাইনাল ট্রান্সফর্ম গণনা করো। এই ক্রমে ম্যাট্রিক্সগুলি গুণ করুন: Viewport * MVP * Normalization. এগুলিকে একটি চূড়ান্ত ট্রান্সফর্মে একত্রিত করলে একটি "ম্যাপ" তৈরি হয় যা ব্রাউজারকে জানায় যে 3D ড্রয়িংয়ের সাথে অ্যালাইন করার জন্য HTML এলিমেন্ট লেয়ারটি ঠিক কোথায় বসানো উচিত।
  • HTML এলিমেন্টে ট্রান্সফর্ম প্রয়োগ করুন। এর ফলে HTML এলিমেন্ট লেয়ারটি রেন্ডার করা পিক্সেলের ঠিক উপরে চলে যায়। এর ফলে ব্যবহারকারী কোনও বোতামে ক্লিক করলে বা টেক্সট বেছে নিলে, তিনি আসল HTML এলিমেন্টে ক্লিক করছেন বলে নিশ্চিত হওয়া যায়।
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.HTMLTexture ব্যবহার করে Three.js-এ পরীক্ষামূলক সহায়তা আছে:

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-এ টেক্সচার API ব্যবহার করে HTML-ইন-ক্যানভাসও কাজ করে:

// 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();

ডেমো

ডেমো ব্যবহার করার আগে, আপনার এনভায়রনমেন্ট ঠিকভাবে কনফিগার করা আছে কিনা তা নিশ্চিত করুন।

API ব্যবহারের রেফারেন্স হিসেবে কাজ করে এমন একাধিক ডেমো রয়েছে। আমরা ইতিমধ্যেই কমিউনিটির থেকে ক্রিয়েটিভ সমাধান দেখতে পাচ্ছি, যার মধ্যে রয়েছে অনুবাদযোগ্য থ্রিডি বই থেকে শুরু করে গ্লাস শেডারের মাধ্যমে রিফ্র্যাক্ট করা UI এলিমেন্ট:

  • 3D বই: একটি WebGL-রেন্ডার করা 3D বই যা এর পৃষ্ঠার জন্য HTML লেআউট ব্যবহার করে। ব্যবহারকারীরা CSS-এর মাধ্যমে ফন্ট অদল-বদল করতে পারবেন। এটি DOM-ভিত্তিক হওয়ায়, বিল্ট-ইন অনুবাদ তৎক্ষণাৎ কাজ করে এবং AI এজেন্টরা কম জটিলতার সাথে টেক্সট এক্সট্র্যাক্ট করতে পারে।
  • ইন্টার‍্যাক্টিভ 3D UI: একটি WebGPU জেলি স্লাইডার যা অন্তর্নিহিত 3D মডেলের উপর ভিত্তি করে আলো রিফ্র্যাক্ট করে, একই সাথে স্ট্যান্ডার্ড HTML <input type="range"> স্টেপ অ্যাট্রিবিউট অনুযায়ী কাজ করে।
  • অ্যানিমেটেড টেক্সচার: কাস্টম অ্যানিমেশন লুপের প্রয়োজন ছাড়াই সরাসরি DOM ব্যবহার করে WebGL টেক্সচারে অ্যানিমেটেড SVG পেন্সিল রেন্ডার করা একটি ডায়নামিক 3D বিলবোর্ড।
  • রিফ্র্যাক্টিভ ওভারলে: একটি মুভিং 3D কার্সরের মাধ্যমে বিকৃত করা একটি ইন্টার‍্যাক্টিভ টাইপোগ্রাফি লেয়ার, তবুও এটি সম্পূর্ণভাবে বেছে নেওয়া যায় এবং ফাইন্ড-ইন-পেজ ব্যবহার করে সার্চ করা যায়।

কমিউনিটির তৈরি করা ডেমোর সংগ্রহ দেখুন। আপনি যদি চান যে আপনার HTML-ইন-ক্যানভাস ডেমো এই সংগ্রহে ফিচার করা হোক, তাহলে এটি যোগ করার জন্য একটি পুল অনুরোধ তৈরি করুন।

সীমাবদ্ধতা

API শক্তিশালী হলেও, এর কিছু সচেতন সীমাবদ্ধতা আছে:

  • ক্রস-অরিজিন কন্টেন্ট: নিরাপত্তা ও গোপনীয়তা সংক্রান্ত কারণে, API ক্রস-অরিজিন iframe কন্টেন্টের সাথে কাজ করে না।
  • মূল থ্রেড স্ক্রলিং: HTML-ইন-ক্যানভাস জাভাস্ক্রিপ্টের মাধ্যমে ড্র করা হয়, যার অর্থ হল, স্ক্রলিং ও অ্যানিমেশন জাভাস্ক্রিপ্ট থেকে আলাদাভাবে আপডেট করা যায় না, যেমন ক্যানভাসের বাইরে করা যায়। ক্যানভাসের মধ্যে স্ক্রল করা যায় এমন কন্টেন্ট রাখা বনাম সম্পূর্ণ ক্যানভাস স্ক্রল করার পারফর্ম্যান্সের বৈশিষ্ট্যগুলি ডেভেলপারদের যত্ন সহকারে বিবেচনা করা উচিত।

মতামত

আপনি যদি HTML-in-Canvas API নিয়ে পরীক্ষা-নিরীক্ষা করে থাকেন, তাহলে আমরা আপনার মতামত জানতে চাই! API ডিজাইনকে আরও উন্নত করতে, এটি পরীক্ষামূলক পর্যায়ে থাকাকালীন আপনার সাইটে ফিচারটি চালু করতে, আপনি অরিজিন ট্রায়ালে সাইন-আপ করতে পারেন। এছাড়াও, কোনও মতামত জানাতে আপনি সমস্যা ফাইল করতে পারেন।

রিসোর্স