Canvas API is used to run graphics, animations, and other exciting things on your website. But running these operations can be resource-intensive and slow down the responsiveness of the user interface.
Canvas operations used to be executed strictly on the main thread since they relied on the
canvas HTML element, which required access to the DOM. Fortunately, that’s no longer the case. In this tutorial, we’ll examine how OffScreenCanvas and Web Workers can help us improve canvas performance.
What is Web Workers API
Web workers are the means of achieving parallel execution in the browser. With them, you can run scripts in background threads.
The main thread and web workers can communicate by setting up event handlers and posting messages using the
To learn more about web workers, check out this documentation page .
What is OffscreenCanvas
Web workers are great but have limited access to browser APIs. For example, you cannot directly manipulate DOM elements from within Web workers - it is only possible from the main thread.
Fortunately, that is where
OffScreenCanvas comes in! The
OffscreenCanvas interface is a canvas that can be rendered off-screen, separating it from the DOM.
OffScreenCanvas is a transferable object, which means you can safely pass it to the web workers and run canvas operations on background threads. In order to send an
OffScreenCanvas instance to a worker, you use
OffScreenCanvas can be synced with a regular canvas using the
transferControlToOffscreen function. Once you do that, the operations performed on the OffScreenCanvas will automatically transfer to the original canvas elements.
How To Set Up OffScreenCanvas with web workers
Now let’s see how we can use
OffScreenCanvas with web workers to boost performance.
Our project will have an
index.js file that kicks off the animation. Here’s what it looks like:
Pretty straightforward: when the script loads, it gets a reference to the
<canvas/> element in our
index.html file and creates an instance of the OffScreenCanvas using the
As you can see, it also initiates our worker and calls the
postMessage on it twice: the first time to transfer the OffScreenCanvas instance to the worker and the second time to trigger the animation.
Now let’s take a look at what our worker script looks like:
Our worker script sets up a listener using the
onmessage function. When our worker receives messages from the main thread, it assigns
canvasMessage to its global
canvas variable. The second time it receives a message, it calls the
animate function to run the canvas animation.
Now, even if our main thread was to become busy and less responsive, that would not affect our worker’s execution. It would still run the animation and update our canvas. And vice-versa, the animation running in the web workers will not stop the UI thread from smoothly responding to user input.
Using it with other libraries
Another nice thing about
OffScreenCanvas is that you can use it to improve the performance of third-party graphics libraries that rely on canvas, like
. Since the
OffscreenCanvas API is generally compatible with the regular
But one thing to be aware of is that OffScreen canvas doesn’t have
style.height properties that some of those libraries might need. In those cases, you can inject those properties in your
OffScreenCanvas instance before passing it to the library.
In this post, we covered how to use OffScreenCanvas to improve the performance of your canvas operations. OffScreenCanvas can be a great way to avoid some of these problems, and it’s simple to use.
To see the full code for this tutorial check out this codesandbox .
If you’d like to get more web development, React and TypeScript tips consider
following me on Twitter,
where I share things as I learn them.