[whatwg] Canvas in Workers

Ian Hickson ian at hixie.ch
Mon Nov 19 10:04:27 PST 2012


On Mon, 19 Nov 2012, Gregg Tavares (社ç~T¨) wrote:
>
> Sorry if this is clear in the specs but can you explain how sizing the 
> canvas works?

There's two sizes involved in a canvas: the size of the bitmap, and the 
size of the rendering. Both default to 300x150 in the absence of explicit 
sizing.

The size of the bitmap, for getContext()-based canvases, is given by the 
<canvas> element's width and height attributes. For rendering contexts 
created by their constructor, it's initially set by the arguments to the 
constructor. It can be changed using the width and height attributes on 
the rendering context. When a context is bound to a canvas, it takes on 
the dimensions of the canvas bitmap. To change the canvas bitmap 
dimensions before calling setContext() or transferControlToProxy(), you 
use the width and height attributes as before. Once you've called 
setContext() or transferControlToProxy(), though, to avoid race conditions 
with workers, only the width and height attributes on the rendering 
context affect the canvas, so you have to first bind the rendering context 
and then set the size if you need the size changed.

The size of the rendering is set by CSS, and defaults to whatever the 
width and height attributes of the canvas element are. Note that if you 
are drawing to the canvas from a worker and you have changed the 
dimensions of the bitmap after you called setContext() or 
transferControlToProxy(), you will have to explicitly set the dimensions 
of the canvas using the element's attributes or CSS, otherwise the canvas 
bitmap will be resized for rendering.


>    // main.html
>    <canvas></canvas>

Here the bitmap and rendering are 300x150.

>    <script>
>     var canvas = document.getElementsByTagName('canvas')[0];
>     var worker = new Worker('clock.js');
>     var proxy = canvas.transferControlToProxy());

At this point, canvas.width/.height no longer affect the bitmap size.

>     worker.postMessage(proxy, [proxy]);
> 
>     setTimeout(function() {
>         canvas.width = 200;   // does this work? What happens?

This just changes the rendered width.

>     }, 4000);
>    </script>
> 
>    // clock.js worker
>    onmessage = function (event) {
>      var context = new CanvasRenderingContext2d();

The constructor could be called with arguments, as in new 
   CanvasRenderingContext2d(200, 150);

That size will have no effect though, since the context is immediately 
bound to a canvas bitmap and takes the bitmap's size:

>      event.data.setContext(context);
>      setInterval(function () {
>        context.width = 400;  // Can I do this? What happens when I do?

This changes the canvas bitmap's dimensions (and resets all state of the 
rendering context). It doesn't change the canvas element's rendered 
dimensions, however (we could push the state out like the bitmap itself, I 
guess, but that would make the DOM change out of the blue which is weird).

>        context.clearRect(0, 0, context.width, context.height);
>        context.fillText(0, 100, new Date());
>        context.commit();
>      }, 1000);
>    };

HTH,
-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


More information about the whatwg mailing list