JavaScript Canvas - OffscreenCanvas
Written by Ian Elliot   
Monday, 16 September 2019
Article Index
JavaScript Canvas - OffscreenCanvas
Using A Worker
transferControlToOffScreen

OffscreenCanvas is relatively new but it can make your graphics smooth without blocking the UI thread. In this extract from a chapter in my new book on JavaScript Graphics we look at how it works.

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas

largecover360

 

Contents

  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
  4. Stroke and Fill
  5. Transformations
  6. Text
  7. Clipping, Compositing and Effects
  8. Generating Bitmaps
  9. WebWorkers & OffscreenCanvas
      Extract 1: OffscreenCanvas
  10. Bit Manipulation In JavaScript
  11. Typed Arrays
  12. Files, blobs, URLs & Fetch
  13. Image Processing
      Extract 1:ImageData **NEW!
  14. 3D WebGL
  15. 2D WebGL

Related Articles

A Programmer's Guide to Canvas

Canvas bitmap operations - bitblt in JavaScript

Reading A BMP File In JavaScript

Getting Started With SVG

SVG, JavaScript and the DOM

Getting started with WebGL

Getting Started with Box2D in JavaScript

<ASIN:1871962625>

<ASIN:1871962579>

<ASIN:1871962560>

<ASIN:1871962501>

<ASIN:1871962528>

Even if you can make your animation run fast enough, you still have the problem of the pauses that occur whenever the UI thread has to deal with something else. There are situations when your animation can freeze for a considerable time. The solution is to move the animation from the UI thread to a different thread.

Until recently there was no way that a JavaScript programmer could take advantage of the OS to schedule threads or multiple cores to implement true parallelism, but now we have web workers which implement background processing on a non-UI thread. The only problem is that a web worker cannot access the DOM and the canvas object is part of the DOM. To make it possible to implement graphics processing off the UI thread, the OffscreenCanvas object was introduced. It is still reasonably new and at the time of writing Chrome is the only browser to fully support it. While supported in Firefox, it is disabled by default and you need to set a flag to enable it, and even then it only supports the WebGL graphics context.

It is worth making clear that while OffscreenCanvas has been introduced as something to make animation smoother, almost any intensive graphics operation is better implemented as a web worker. Indeed any intensive operation of any kind is best implemented in this way.

Before we look at how to use OffscreenCanvas we need to find out the basics of using a web worker. This is explained in detail in the chapter but here is a summary:

  • Communication between the UI and worker thread is via events fired by one thread and received by the other.

  • Each thread only processes events when not occupied with running code.

  • This means that events may not be dealt with promptly.

  • Data can be transferred between threads using the event object that is made available to the event handler.

  • Data is not shared – a copy is made for the receiving thread.

  • The UI thread is generally set up to respond to events promptly, but the worker thread isn’t.

  • A graphics-oriented worker thread is the exception to the rule as it generally gives up its thread with each call to requestAnimationFrame.

Sections in book but not in this extract:

  • Basic Web Worker
  • The Trouble With Threads
  • Basic Communication Methods
  • UI Thread to Worker Thread
  • Worker Thread to UI Thread
  • Transferable Objects

OffscreenCanvas

An OffscreenCanvas is a canvas object that isn’t part of the screen display. It is simply an area of memory that you can draw into using all of the familiar methods. The fact that it isn’t part of the display, and isn’t part of the DOM, means that it can be used from the UI thread and from a worker thread. When used from the UI thread it behaves a lot like a canvas object that you haven’t added to the DOM, but it also has some additional methods.

You create an OffscreenCanvas object using:

var offCanvas=new OffscreenCanvas(width,height);

Notice that as this is not part of the DOM it doesn’t have a style width and height like a canvas object. It does have width and height properties, however. It also has a getContext method that you can use to draw on it and a pair of new methods:

  • convertToBlob() converts the image to a binary blob using the format of any of the supported graphics file types – jpg, png. For lossy compression you can also specify a quality parameter.

  • transferToImageBitmap() returns an ImageBitmap object based on the current contents of the OffscreenCanvas.

OffscreenCanvas in the UI Thread

As already mentioned, you can use an OffscreenCanvas wherever you would otherwise use a canvas object not added to the DOM and, as long as you are only targeting browsers that support OffscreenCanvas, it is sensible to use it instead. However, at the time of writing only Chrome supports it in the 2d context.

For example, the bitmap for the ball in the example at the end of the previous chapter can be created using, in the main program;

var ctx2 = new OffscreenCanvas(40, 40).getContext("2d");
var path = new Path2D();
var r = 20;
path.arc(20, 20, r, 0, 2 * Math.PI);
ctx2.fill(path);

And to make this visible you simply use, in render:

ctx.drawImage(ctx2.canvas, this.pos.x - r,
this.pos.y – r);

which is exactly how you would do it with a standard canvas object.

You can see the complete modified program at www.iopress.info.

Alternatively you could create an ImageBitmap and use it in place of the canvas:

var ballImage=ctx2.canvas.transferToImageBitmap();

You would then render the ball using:

ctx.drawImage(ballImage, this.pos.x - r, this.pos.y – r);

which is in principle faster.



Last Updated ( Monday, 16 September 2019 )