1

In our product we've run into an issue where a canvas is sometimes created that exceeds the limits set by browsers (I got the limits from this question).

In trying to come up with a way to warn users or at least to salvage the operation, I wanted to see if I could wrap the canvas initialization in a try/catch statement, something like this:

createCanvas = function() {
  var element = document.createElement("canvas");
  element.id = "canvasId";
  document.getElementById("container").appendChild(element);
  return element;
};

tryToCreateCanvas = function() {
  var width = document.getElementById("widthInput").value;
  var height = document.getElementById("heightInput").value;
  var element = createCanvas();
  try {
    element.width = width;
    element.height = height;
    var context = element.getContext("2d");
    context.scale(width, height);
    document.getElementById("result").innerHTML = "Success!";
  } catch (e) {
    document.getElementById("result").innerHTML = "Failure!";
  }
};

In firefox, creating a canvas that is too large throws an exception and everything works correctly.

Chrome however, crashes the canvas (shows the little out of memory icon), but doesn't throw an exception, so I don't know how to catch the fact that the canvas failed to create.

So basically, the code above will show Success in Chrome/Opera, Failure in Firefox, and both canvases do not work.

Does anyone know of a reliable way to check whether the canvas is functional in Chrome?

I've created this fiddle to illustrate what's going on

Kolichikov
  • 2,944
  • 31
  • 46

1 Answers1

0

You can simply try to draw something on that canvas, and check if it worked by reading the pixels using ctx.getImageData:

const ctx = canvas.getContext('2d');
size.onchange = e => {
  const newSize = +size.value;
  console.log(newSize + ' x ' + newSize, testValidSize(newSize));
};
size.onchange();

function testValidSize(width, height = width) {
  try {
    canvas.width = width;
    canvas.height = height;
    ctx.fillRect(0,0,1,1);  // fill a single pixel
    // check its alpha value
    const supported = !!ctx.getImageData(0,0,1,1).data[3];
    ctx.clearRect(0,0,width,height); // clean
    return supported;
  }
  catch(e) {
    return false;
  }

}
<input type="number" value="50000" id="size">
<canvas id="canvas"></canvas>

But beware, on very large canvas you may have a lot of slowness even though you could draw on the canvas.

Kaiido
  • 123,334
  • 13
  • 219
  • 285