59

HTML:

  <div class="canvas-wrapper">
    <canvas id="myCanvas"></canvas>
  </div>

CSS

.canvas-wrapper {
    width: 900px;
    min-height: 600px;
 }

 #myCanvas{
     border:1px solid red;
     position: absolute;
     top:22px;
     left:0px;
     height: 100%;
     width: 99%;
 }

JS

var myCanvas = new fabric.Canvas('myCanvas');

My canvas get resized to 300x150 after it's been initialized, why?

Cœur
  • 37,241
  • 25
  • 195
  • 267
user469652
  • 48,855
  • 59
  • 128
  • 165

3 Answers3

87

in the latest version, you will have to do something like:

var canvas = new fabric.Canvas('myCanvas');
canvas.setHeight(500);
canvas.setWidth(800);

.... Your code ....

canvas.renderAll();

Works fine for me..

For dynamically changing size, this works too

Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
Smit
  • 1,559
  • 17
  • 38
  • This is by far the easiest way I've found to do this. – Nick Larsen Jan 11 '13 at 15:55
  • 3
    You should add this in the end to recalculate all the objects positions: canvas.calcOffset(); – JR. Sep 23 '13 at 16:48
  • 21
    How can I set the canvas to be 100% the width and height of the parent component? I don't understand why this is so much more difficult that any other component that respects the 100% css attributes and every answer out there just shows how to set to a fixed width/height. – krb686 Mar 06 '16 at 16:34
27

When initializing canvas, Fabric reads width/height attributes on canvas element or takes width/height passed in options.

var myCanvas = new fabric.Canvas('myCanvas', { width: 900, height: 600 });

or:

<canvas width="900" height="600"></canvas>
...
var myCanvas = new fabric.Canvas('myCanvas');
kangax
  • 38,898
  • 13
  • 99
  • 135
  • Seems like we have to do this. – user469652 May 15 '12 at 12:26
  • 1
    @kangax , I have multiple canvas elements on my page and all of them are positioned on runtime with some js calculation. A user can also add more canvas elements. Creating fabric.canvas("canvas1") makes them lose their position. I tried, as you suggested: $jArtB = $("#"+artB); c = new fabric.Canvas(''+artB, { width: $jArtB.width(), height: $jArtB.height(), left:parseInt($jArtB.css("left")), top:parseInt($jArtB.css("top")) }); ` . But this isn't working either. – ScorpionKing2k5 Jul 30 '13 at 12:22
  • 1
    Is there an effective way how to resize canvas to fit the image dimensions that is being loaded using fabric.Image.fromURL ? Thanks – tomexx Mar 05 '15 at 13:35
1

A real answer to this question—not involving a new static size but actually permitting CSS to be effective—is one of the following options:

  1. In CSS, you can override individual properties and following them with !important; the downside to this is that any further definitions must also use !important or they will be ignored:
[width], [height], [style]
{
  width:      100vw!important;
  min-height: 100vh!important;
}
  1. Using JQuery you can set the inline property values to an empty string. You can presumably achieve this without JQuery, but I will leave that as an exercise to you.

Javascript (JQuery):

$('[style]').attr(  'style',  function(index, style){  return ''; });
$('[height]').attr( 'height', function(index, height){ return ''; });
$('[width]').attr(  'width',  function(index, height){ return ''; });

CSS:

*, *:before, *:after
{
  box-sizing: border-box;
}

body
{
  width:      100vw; 
  min-height: 100vh;
  padding:    0;
  margin:     0;
}

.canvas-container,
canvas
{
  width:      inherit; 
  min-height: inherit;
}

canvas.lower-canvas
{
  position: absolute;
  top:      0;
}

After that, CSS will be applied as expected.

It is apparently also necessary to tell Fabric about the change:

function sizeCanvas()
{
  var width  = Math.max(document.documentElement.clientWidth,  window.innerWidth  || 0);
  var height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  canvas.setHeight( height )
  canvas.setWidth( width )
}

window.addEventListener('resize', draw, false);

function initDraw()
{
  // setup
}

function draw()
{  
  canvas.renderAll();  
}

sizeCanvas();
initDraw();

This will configure Fabric to the viewport size and keep it sized accordingly if it resizes.

It's worth noting that this problem arises for two reasons:

  1. Someone thought it was a good idea to use inline styles and should be severely castigated, as there is no situation where this is ever an appropriate practice.

  2. Fabric changes the DOM arrangement and nests the original canvas in a new div with a second nested canvas, which may result in surprises.

Asher
  • 1,195
  • 1
  • 11
  • 19
  • While this answer is useful, and I think many people agree that statically defining the canvas size is less than ideal, perhaps the wording could be changed to be less abrasive. – MirroredFate Dec 24 '19 at 17:36