Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
    }
}
like image 577
Maël Nison Avatar asked Sep 03 '11 14:09

Maël Nison


2 Answers

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)

like image 56
Simon Sarris Avatar answered Oct 07 '22 15:10

Simon Sarris


Rather than have two canvases overlaying, the solution I went with was to replace the existing canvas with a clone of itself.

var newCvs = cvs.cloneNode(false);
cvs.parentNode.replaceChild(newCvs, cvs);
cvs = newCvs;

All the properties of the original canvas will be retained but the context will be freed up to allocate as you wish.

like image 41
Fergal Avatar answered Oct 07 '22 13:10

Fergal