Maël Nison Maël Nison - 4 months ago 13
HTML Question

Switch canvas context

Assuming that I have a WebGL canvas (by calling getContext("experimental-webgl")).

Is there any way to switch context later for using a "2d" one ?

The goal of such thing would be to display a debug BSOD-like when an error happening during rendering.

If it's not possible, then :


  • Can I embed an html element over a canvas, and force this element to have exactly the same same that the canvas (even if this last is resized) ?

  • Can I replace an dom node, and update every reference about the old one to reflect the changement ?



[edit] This is my current minimal call code. Canvas is a DOM node containing a canvas which is filled by WebGL API, and callback is a function which process a single frame.

function failure(cvs, e) {
var ctx = cvs.getContext('2d'); // Fail here, returns `null' if cvs.getContext('webgl') has been called
ctx.fillStyle = 'rgb(0, 0, 0)';
ctx.fillRect(0, 0, cvs.width, cvs.height);
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.font = 'bold 12px sans-serif';
ctx.fillText(e.toString(), 0, 0);
}

function foobar(canvas, callback) {
try {
callback();
} catch (e) {
failure(canvas, e);
throw e;
} finally {
requestAnimationFrame(arguments.callee);
}
}

Answer

The short answer is pretty much no, according to the spec.

Every canvas has what is called a primary context. This is the first context that is invoked on a canvas. Making a non-primary context on a canvas might do some things on different browsers but I would never, ever depend on it.

I would instead have a second canvas that is overlaid over the first and maintains the same width and height attributes. I would then hide one and unhide the other (or just unhide the 2D one when you want it seen).

OR just use a PNG for simplicity's sake., centered inside of a DIV that also holds the canvas. In other words:

 Div container has black background and holds:
   -PNG (centered)
   -3D Canvas

Then when you want the error png to be displayed you just hide the 3D canvas (and optionally unhide the PNG)