Send offscreencanvas to webworker more than once

梦想的初衷 提交于 2020-07-22 08:33:48

问题


I want to be able to send my canvas offscreen to a webworker more than once.

Here's an example code:

render() {
  const worker = new Worker("some url");
  const offscreen = this.canvasRef.current.transferControlToOffscreen();
  this.worker.postMessage({
    offscreen
  }, [offscreen]);

  return (
    <canvas ref={this.canvasRef} height="800" width="1000" />
  );
}

The idea is to be able to kill the web worker if user decides to cancel the drawing. Put when I repost the message to a new web worker, I get the following error:

DataCloneError: Failed to execute 'postMessage' on 'Worker':
An OffscreenCanvas could not be cloned because it was detached.

回答1:


You could send it more than once, but for this, you'd need to transfer it back from the worker, which kind of defeats your purpose I guess since the worker would need to be free to be able to handle that request, and if it is, there is no need to "kill" it.

So instead, you may prefer to create a standalone OffscreenCanvas, using the eponymous constructor that will stay in the Worker and to draw it on a BitmapRenderingContext:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('bitmaprenderer');

const stop_btn = document.getElementById('stop_btn');

document.getElementById('start_btn').onclick = e => {
  console.log( 'starting a new drawing' );
  const worker = new Worker(getWorkerURL());
  worker.onmessage = e => {
    console.log('drawing complete');
    // pass it to the visible canvas
    ctx.transferFromImageBitmap(e.data);
    start_btn.disabled = false;
    stop_btn.disabled = true;
  };
  stop_btn.onclick = e => {
    console.log('drawing canceled');
    worker.terminate();
    start_btn.disabled = false;
    stop_btn.disabled = true;
  };
  start_btn.disabled = true;
  stop_btn.disabled = false;
};

function getWorkerURL() {
  const el = document.getElementById('worker_script');
  const blob = new Blob([el.textContent]);
  return URL.createObjectURL(blob);
}
<button id="start_btn">start</button>
<button id="stop_btn">stop</button><br>

<canvas id="canvas" width="500" height="500"></canvas>
<script id="worker_script" type="ws">
  const canvas = new OffscreenCanvas(500, 500);
  const gl = canvas.getContext('webgl');
  gl.viewport(0, 0,
      gl.drawingBufferWidth, gl.drawingBufferHeight);
  gl.enable(gl.SCISSOR_TEST);
  // make some slow noise (we're in a Worker)
  for(let y=0; y<gl.drawingBufferHeight; y++) {
    for(let x=0; x<gl.drawingBufferWidth; x++) {
      gl.scissor(x, y, 1, 1);
      gl.clearColor(Math.random(), Math.random(), Math.random(), 1.0);
      gl.clear(gl.COLOR_BUFFER_BIT);
    }
  }
  // make it last a bit longer than really needed
  const start = Date.now();
  while ( Date.now() - start < 5000 ) { }

  const img = canvas.transferToImageBitmap();
  postMessage(img, [img]);

</script>


来源:https://stackoverflow.com/questions/59598111/send-offscreencanvas-to-webworker-more-than-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!