多次将屏外画布发送给Webworker

问题描述 投票:0回答:1

我希望能够多次将我的画布从屏幕外发送给Webworker。

这是示例代码:

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

想法是如果用户决定取消绘图,则可以杀死网络工作者。当我将消息重新发布到新的Web工作人员时,出现以下错误:

DataCloneError: Failed to execute 'postMessage' on 'Worker':
An OffscreenCanvas could not be cloned because it was detached.
canvas web-worker
1个回答
0
投票

您可以多次发送它,但是为此,您需要将其从工作人员那里转移回来,我认为这违背了您的目的,因为工作人员将需要自由地能够处理该请求,如果是的话,则无需“杀死”它。

因此,您可能更喜欢使用将留在Worker中的同义constructor创建一个独立的OffscreenCanvas,并将其绘制在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>
© www.soinside.com 2019 - 2024. All rights reserved.