在 JavaScript 的 Web Worker (worker.js) 中创建图像

ton*_*ark 2 javascript web-worker offscreen-canvas

我正在重写一个小的 javascript,以便能够将其放入worker.js 中,就像这里记录的那样:

Mozilla - Web_Workers_API

worker.js 应在 OffscreenCanvas 上显示图像,如下所示:

Mozilla - OfscreenCanvas 文档

初始脚本使用以下语句,显然不能在worker.js文件中使用,因为没有“文档”:

    var imgElement = document.createElement("img");
    imgElement.src = canvas.toDataURL("image/png");
Run Code Online (Sandbox Code Playgroud)

但我怎样才能代替

document.createElement("img");
Run Code Online (Sandbox Code Playgroud)

在worker.js中声明仍然可以使用第二个语句:

imgElement.src = canvas.toDataURL("image/png");
Run Code Online (Sandbox Code Playgroud)

如果有人有任何想法,我们将不胜感激。:)

Kai*_*ido 7

只是不要。

无需导出画布内容并使浏览器解码该图像以仅显示它,只需直接显示 HTMLCanvasElement 即可。

在您切换到 OffscreenCanvas 之前,这个建议已经代表了,但它仍然适用。

那么如何在Worker中的OffscreenCanvas上绘制并仍然显示呢?我听到你问。

transferControlToOffscreen()那么,您可以通过 HTMLCanvasElement 的方法从 HTMLCanvasElement 请求 OffscreenCanvas 。

因此,正确的方法是,在 UI 线程中,生成<canvas>将用于显示图像的元素,并从中生成 OffscreenCanvas。然后启动您的 Worker,并将 OffscreenCanvas 传输到其中。
在 Worker 中,您将等待 onmessage 事件中的 OffscreenCanvas 并获取上下文并在其上绘图。

用户界面线程

const canvas = document.createElement("canvas");
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker(url);
worker.postMessage(offscreen, [offscreen]);
container.append(canvas);
Run Code Online (Sandbox Code Playgroud)

工作线程

onmessage = (evt) => {
  const canvas = evt.data;
  const ctx = canvas.getContext(ctx_type);
  //...
Run Code Online (Sandbox Code Playgroud)

所有由 Worker 绘制的绘图都将绘制在可见画布上,而完全不会阻塞 UI 线程。

const canvas = document.createElement("canvas");
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker(url);
worker.postMessage(offscreen, [offscreen]);
container.append(canvas);
Run Code Online (Sandbox Code Playgroud)
onmessage = (evt) => {
  const canvas = evt.data;
  const ctx = canvas.getContext(ctx_type);
  //...
Run Code Online (Sandbox Code Playgroud)
const canvas = document.querySelector("canvas");
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker(getWorkerURL());
worker.postMessage(offscreen, [offscreen]);


function getWorkerURL() {
  const worker_script = `
  onmessage = (evt) => {
    const canvas = evt.data;
    const w = canvas.width = 500;
    const h = canvas.height = 500;
    const ctx = canvas.getContext("2d");
    // draw some noise
    const img = new ImageData(w,h);
    const arr = new Uint32Array(img.data.buffer);
    for( let i=0; i<arr.length; i++ ) {
      arr[i] = Math.random() * 0xFFFFFFFF;
    }
    ctx.putImageData(img, 0, 0);
    for( let i = 0; i < 500; i++ ) {
      ctx.arc( Math.random() * w, Math.random() * h, Math.random() * 20, 0, Math.PI*2 );
      ctx.closePath();
    }
    ctx.globalCompositeOperation = "xor";
    ctx.fill();
  };
  `;

  const blob = new Blob( [ worker_script ] );
  return URL.createObjectURL( blob );
}
Run Code Online (Sandbox Code Playgroud)