【问题标题】:Create an image in JavaScript's Web Worker (worker.js)在 JavaScript 的 Web Worker (worker.js) 中创建图像
【发布时间】:2021-07-06 17:03:51
【问题描述】:

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

Mozilla - Web_Workers_API

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

Mozilla - OfscreenCanvas documentation

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

    var imgElement = document.createElement("img");
    imgElement.src = canvas.toDataURL("image/png");

但是我该如何替换

document.createElement("img");

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

imgElement.src = canvas.toDataURL("image/png");

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

【问题讨论】:

    标签: javascript web-worker offscreen-canvas


    【解决方案1】:

    虽然您无法在工作线程上创建元素,但您可以将结果发送回 document 对象所在的主线程。

    根据您提供的docs of MDN,没有toDataURL() 方法。但是有一个OffscreenCanvas.convertToBlob() 方法可以从屏幕外画布创建一个Blob

    使用postMessage 将 blob 发送到主线程并在那里继续。

    const offscreenCanvas = new OffscreenCanvas(1920, 1080);
    
    const sendImage = async () => {
      const blob = await offscreenCanvas.convertToBlob({
        type: "image/jpeg",
        quality: 0.95
      });
    
      self.postMessage(blob);
    };
    
    sendImage();
    

    接收Blob 并从中创建图像。

    注意:canvas.toDataURL 基本上是BlobURL.createObjectURL() 的组合,所以最终结果是一样的。

    const worker = new Worker('./worker.js');
    
    const createImageFromBlob = blob => {
      const image = new Image();
      image.src = URL.createObjectURL(blob);
      return image;
    };
    
    worker.addEventListener('message', ({ data }) => {
      const image = createImageFromBlob(data);
    });
    

    【讨论】:

    • 正是我正在寻找的。非常感谢!
    • 不客气。请不要忘记将答案标记为已接受。这样,其他人将看到相同的问题的答案。这是一种表示感谢的方式!
    • 这是一种糟糕的做法,你不仅要求浏览器做比它需要做的更多的工作,而且你甚至违背了在第一名。
    【解决方案2】:

    别这样。

    与其导出画布内容并让浏览器仅解码该图像以显示它,不如直接直接显示 HTMLCanvasElement。

    在您切换到 OffscreenCanvas 之前,这个建议已经存在,但它仍然存在。

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

    好吧,您可以通过其transferControlToOffscreen() method 从 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);
    

    工作线程

    onmessage = (evt) => {
      const canvas = evt.data;
      const ctx = canvas.getContext(ctx_type);
      //...
    

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

    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 );
    }
    canvas { border: 1px solid; }
    &lt;canvas&gt;&lt;/canvas&gt;

    【讨论】:

    • 感谢您的澄清。引用:“在 Worker 中,您将等待 onmessage 事件中的 OffscreenCanvas 并获取上下文并在其上绘制。”也许这很明显,我只是不明白,但是看看我最初的问题,我该如何替换命令: var imgElement = document.createElement("img"); ...因为我仍然没有“文件”。我在这里想念什么? ://
    • 您不要替换此行。你根本不需要 。我在底部提供了一个实时的 sn-p,满足您的所有需求。
    猜你喜欢
    • 2014-06-24
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 2020-08-28
    • 2022-11-02
    • 1970-01-01
    相关资源
    最近更新 更多