How to resize html canvas element?

JavascriptHtmlCanvasDhtml

Javascript Problem Overview


I have a canvas element defined statically in the html with a width and height. If I attempt to use JavaScript to resize it dynamically (setting a new width and height - either on the attributes of the canvas or via the style properties) I get the following error in Firefox:

> uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///home/russh/Desktop/test.html :: onclick :: line 1" data: no]

Is it possible to resize this element or do I have to destroy it and create a new element on the fly?

Javascript Solutions


Solution 1 - Javascript

You didn't publish your code, and I suspect you do something wrong. it is possible to change the size by assigning width and height attributes using numbers:

canvasNode.width  = 200; // in pixels
canvasNode.height = 100; // in pixels

At least it works for me. Make sure you don't assign strings (e.g., "2cm", "3in", or "2.5px"), and don't mess with styles.

Actually this is a publicly available knowledge — you can read all about it in http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element">the HTML canvas spec — it is very small and unusually informative. This is the whole DOM interface:

interface HTMLCanvasElement : HTMLElement {
           attribute unsigned long width;
           attribute unsigned long height;

  DOMString toDataURL();
  DOMString toDataURL(in DOMString type, [Variadic] in any args);

  DOMObject getContext(in DOMString contextId);
};

As you can see it defines 2 attributes width and height, and both of them are unsigned long.

Solution 2 - Javascript

Note that if your canvas is statically declared you should use the width and height attributes, not the style, eg. this will work:

<canvas id="c" height="100" width="100" style="border:1px"></canvas>
<script>
    document.getElementById('c').width = 200;
</script>

But this will not work:

<canvas id="c" style="width: 100px; height: 100px; border:1px"></canvas>
<script>
    document.getElementById('c').width = 200;
</script>

Solution 3 - Javascript

I just had the same problem as you, but found out about the toDataURL method, which proved useful.

The gist of it is to turn your current canvas into a dataURL, change your canvas size, and then draw what you had back into your canvas from the dataURL you saved.

So here's my code:

var oldCanvas = canvas.toDataURL("image/png");
var img = new Image();
img.src = oldCanvas;
img.onload = function (){
	canvas.height += 100;
	ctx.drawImage(img, 0, 0);
}

Solution 4 - Javascript

<div id="canvasdiv" style="margin: 5px; height: 100%; width: 100%;">
    <canvas id="mycanvas" style="border: 1px solid red;"></canvas>
</div>
<script>
$(function(){
    InitContext();
});
function InitContext()
{
var $canvasDiv = $('#canvasdiv');

var canvas = document.getElementById("mycanvas");
canvas.height = $canvasDiv.innerHeight();
canvas.width = $canvasDiv.innerWidth();
}
</script>

Solution 5 - Javascript

This worked for me just now:

<canvas id="c" height="100" width="100" style="border:1px solid red"></canvas>
<script>
var c = document.getElementById('c');
alert(c.height + ' ' + c.width);
c.height = 200;
c.width = 200;
alert(c.height + ' ' + c.width);
</script>

Solution 6 - Javascript

Here's my effort to give a more complete answer (building on @john's answer).

The initial issue I encountered was changing the width and height of a canvas node (using styles), resulted in the contents just being "zoomed" or "shrunk." This was not the desired effect.

So, say you want to draw two rectangles of arbitrary size in a canvas that is 100px by 100px.

<canvas width="100" height="100"></canvas>

To ensure that the rectangles will not exceed the size of the canvas and therefore not be visible, you need to ensure that the canvas is big enough.

var $canvas = $('canvas'),
    oldCanvas,
    context = $canvas[0].getContext('2d');

function drawRects(x, y, width, height)
{
  if (($canvas.width() < x+width) || $canvas.height() < y+height)
  {
    oldCanvas = $canvas[0].toDataURL("image/png")
    $canvas[0].width = x+width;
    $canvas[0].height = y+height;

    var img = new Image();
    img.src = oldCanvas;
    img.onload = function (){
      context.drawImage(img, 0, 0);
    };
  }
  context.strokeRect(x, y, width, height);
}


drawRects(5,5, 10, 10);
drawRects(15,15, 20, 20);
drawRects(35,35, 40, 40);
drawRects(75, 75, 80, 80);

Finally, here's the jsfiddle for this: http://jsfiddle.net/Rka6D/4/ .

Solution 7 - Javascript

Prototypes can be a hassle to work with, and from the _PROTO part of the error it appears your error is caused by, say, HTMLCanvasElement.prototype.width, possibly as an attempt to resize all the canvases at once.

As a suggestion, if you are trying to resize a number of canvases at once, you could try:

<canvas></canvas>
<canvas></canvas>
<canvas></canvas>
<script type="text/javascript">
    ...
</script>

In the JavaScript, instead of invoking a prototype, try this:

$$ = function(){
    return document.querySelectorAll.apply(document,arguments);
}
for(var i in $$('canvas')){
    canvas = $$('canvas')[i];
    canvas.width = canvas.width+100;
    canvas.height = canvas.height+100;
}

This would resize all the canvases by adding 100 px to their size, as is demonstrated in this example


Hope this helped.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionrussx2View Question on Stackoverflow
Solution 1 - JavascriptEugene LazutkinView Answer on Stackoverflow
Solution 2 - Javascriptsam hocevarView Answer on Stackoverflow
Solution 3 - JavascriptjohnView Answer on Stackoverflow
Solution 4 - JavascriptJignesh VariyaView Answer on Stackoverflow
Solution 5 - JavascriptKent BrewsterView Answer on Stackoverflow
Solution 6 - JavascriptGezimView Answer on Stackoverflow
Solution 7 - JavascriptBraden BestView Answer on Stackoverflow