Is it possible to create an HTML canvas without a DOM element?

Viewed 48944

I'd like to have an HTML canvas context that I can paint to and read off-screen (in this example, writing text and reading the shape that is created, but it's a general question). I may also want to use a canvas as an off-screen frame-buffer.

I suppose I could create a hidden DOM element but I'd rather create it from JavaScript (I may want to create and destroy a number of canvas at runtime).

Possible?

4 Answers

There is apparently a new thing called OffscreenCanvas that was deliberately designed for this use case. An additional bonus is that it also works in Web Workers.

You can read the specifications here: https://html.spec.whatwg.org/multipage/canvas.html#the-offscreencanvas-interface

And see examples here: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas

Currently it is only fully supported by Chrome and is available behind flags in Firefox and Opera, but you can always check for the latest information on supported browsers here: https://caniuse.com/#feat=offscreencanvas

ps.: Google also has a dedicated guide explaining it's use in Web Workers: https://developers.google.com/web/updates/2018/08/offscreen-canvas

Both the CanvasRenderingContext2D and WebGLRenderingContext classes have the canvas element associated with them as the property canvas; and, like normal, both context instances and their canvases will be garbage collected when your code no longer makes references to them at run time.

You can use this function to create a new context

function newContext({width, height}, contextType = '2d') {
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    return canvas.getContext(contextType);
}

const ctx = newContext({width: 100, height: 100});
console.log(ctx.canvas.width == 100) // true

And by making use of dereferencing you can easily create a clone of a DOM canvas for frame buffering like this:

const domCanvas = document.getElementById('myCanvas');

const frameBuffer = newContext(domCanvas);
frameBuffer.drawImage(domCanvas, 0, 0);

Which will create a context with the same width and height as the canvas element passed in. You can extend the function as needed.

Related