Search code examples
javascripthtml5-canvasweb-workerdrawimage

Using Web Workers for drawing using native canvas functions


It's possible to send a CanvasPixelArray obtained via getImageData to a worker script, and let the worker script manipulate the pixels in its background thread, and eventually post the manipulated pixel array back.

However, I'm using native canvas drawing functions, like drawImage. The drawImage calls are currently blocking the UI thread. This causes slow redraw of buttons, and a noticeable delay when clicking on a button, just to name a few drawbacks. (Edit: A small improvement can now be accomplished with ctx.imageSmoothingEnabled = false, at least on WebKit with the webkit prefix.)

I'd like to move the drawing from the main thread into a background thread using Web Workers. However, I don't seem to be able to send the canvas nor the context to the worker.

I did find this notice on MDN:

Note: As usual, background threads—including workers—cannot manipulate the DOM. If actions taken by the background thread need to result in changes to the DOM, they should post messages back to their creators to do that work.

But I would like to leave the DOM as-is; I simply want to draw things on a canvas element. Is this possible, or are Web Workers really only allowed to calculate and not to draw?

(Or is it perhaps possible to use functions like drawImage to manipulate a CanvasPixelArray instead of drawing on a canvas?)


Solution

  • [community edit: This answer was written and accepted in 2011. Other technologies have emerged (or are emerging) which may allow Web Workers and Canvas to co-exist better; the reader should be aware of all the answers on this page besides this answer.]

    You cannot pass a canvas object or canvas context to a worker thread because the canvas is part of the DOM.