我希望能够多次将我的画布从屏幕外发送给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.
您可以多次发送它,但是为此,您需要将其从工作人员那里转移回来,我认为这违背了您的目的,因为工作人员将需要自由地能够处理该请求,如果是的话,则无需“杀死”它。
因此,您可能更喜欢使用将留在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>