Capítulo 833 de 859

Chapter 833: OffscreenCanvas (Manual)

Core Idea

OffscreenCanvas lets a web worker own and render to a canvas, moving heavy three.js rendering (and asset loading/parsing) off the main thread so the page stays responsive — at the cost of the worker having no DOM access at all.

Key Concepts

  • canvas.transferControlToOffscreen(): hands control of a <canvas> element to an OffscreenCanvas object that can be transferred into a worker.
  • new Worker(path, { type: "module" }) + postMessage: starts the worker and sends it the offscreen canvas; the second argument to postMessage lists objects (like the offscreen canvas) to transfer rather than clone — transferred objects become unusable back on the main thread.
  • No DOM in workers: a worker can't read canvas.clientWidth/clientHeight, receive mouse/keyboard events, or touch any DOM API — all of that must be explicitly forwarded from the main thread via messages.
  • Message-based dispatch: a simple { type, ...data } convention on both ends lets the main thread and worker route messages to the right handler function.
  • Feature detection + fallback: check for canvas.transferControlToOffscreen before using this path, and fall back to normal main-thread rendering (sharing the same core three.js code) when unsupported.
  • Forwarding input events: mouse/touch/keyboard/wheel events must be serialized (copying only the needed properties) and sent to the worker via postMessage, since the worker can't listen for them itself.

Code Examples

function makeSendPropertiesHandler(properties) {
  return function sendProperties(event, sendFn) {
    const data = { type: event.type };
    for (const name of properties) data[name] = event[name];
    sendFn(data);
  };
}

const mouseEventHandler = makeSendPropertiesHandler([
  "ctrlKey", "metaKey", "shiftKey", "button", "clientX", "clientY",
]);
  • What it demonstrates: a small factory for forwarding just the needed properties of a DOM event to a worker, since full Event objects can't be structured-cloned.

Key Takeaways

  1. OffscreenCanvas moves rendering (and ideally loading/parsing) off the main thread, which can reduce jank during heavy scenes or page load.
  2. Transferring an object via postMessage's second argument neuters it on the sending side — the main-thread offscreen reference becomes unusable after transfer.
  3. Workers have zero DOM access, so canvas size, resize events, and all input events must be explicitly serialized and forwarded from the main thread.
  4. Structure shared three.js logic into a common module so the same rendering code can run either in the worker or as a main-thread fallback when OffscreenCanvas isn't supported.

Connects To

  • OrbitControls / PickHelper: examples of interactive features that need extra event-forwarding work to function inside a worker.