How to enable responsive design for Fabric.js

This jsFiddle is a working solution. It is inspired by this github issue.

These are the required things:

A div that surrounds the canvas that is controlled by fabric.

<div class="fabric-canvas-wrapper">
    <canvas id="theCanvas"></canvas>
</div>

And a window resize handler that triggers the calculation and setting of the new canvas dimension and the zoom.

window.onresize = resizeCanvas() {
    const outerCanvasContainer = document.getElementById('fabric-canvas-wrapper');

    const ratio          = canvas.getWidth() / canvas.getHeight();
    const containerWidth = outerCanvasContainer.clientWidth;
    const scale          = containerWidth / canvas.getWidth();
    const zoom           = canvas.getZoom() * scale;

    canvas.setDimensions({width: containerWidth, height: containerWidth / ratio});
    canvas.setViewportTransform([zoom, 0, 0, zoom, 0, 0]);
}

That's all. It seems to work perfectly. Please let me know if any issues come up with this solution.

I have used fabric.js in version 3.6.2.


i thought this one was the answer I needed https://stackoverflow.com/a/29445765/1815624

it seemed so close but after some adjustments I got what I wanted it down scales when needed and maxes out at a scale of 1.

The canvas size you desire should be set as width/height var optimal_dimensions = [1000,1000];

this needs some more changes to handle height as well so when a user rotates there phone to landscape it may become to big to see it all on the screen the new edited code will be at 1000 pixels in width and height for this demo

update: added detection for height and width to scale to window...

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" width="1000" height="1000"></canvas>

    

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.0.0/fabric.min.js"></script>
   <script>
  var canvas = new fabric.Canvas('canvas');
  canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));

  canvas.item(0).set({
    borderColor: 'gray',
    cornerColor: 'black',
    cornerSize: 12,
    transparentCorners: true
  });
  canvas.setActiveObject(canvas.item(0));
  canvas.renderAll();

 
function rescale_canvas_if_needed(){
    var optimal_dimensions = [400,400];
    var scaleFactorX=window.innerWidth/optimal_dimensions[0];
    var scaleFactorY=window.innerHeight/optimal_dimensions[1];
    if(scaleFactorX <  scaleFactorY && scaleFactorX < 1) {
        canvas.setWidth(optimal_dimensions[0] *scaleFactorX);
        canvas.setHeight(optimal_dimensions[1] *scaleFactorX);
        canvas.setZoom(scaleFactorX);
    } else if(scaleFactorX >  scaleFactorY && scaleFactorY < 1){
        canvas.setWidth(optimal_dimensions[0] *scaleFactorY);
        canvas.setHeight(optimal_dimensions[1] *scaleFactorY);
        canvas.setZoom(scaleFactorY);
    }else {
        canvas.setWidth(optimal_dimensions[0] );
        canvas.setHeight(optimal_dimensions[1] );
        canvas.setZoom(1);
    }

    canvas.calcOffset();
    canvas.renderAll();
}

 
function handle_resize(){
    $(".canvas-container").hide();
    rescale_canvas_if_needed();
    $(".canvas-container").show();               
     
}
var resizeId = null;
$(function() {
    $(window).resize(function() {
        if(resizeId != null)
        clearTimeout(resizeId);
        resizeId = setTimeout(handle_resize, 500);
     });
    console.log( "ready!" );
    /* auto size it right away... */
    resizeId = setTimeout(handle_resize, 500);
});
    </script>

hope this helps someone...good day.


Basically you need to get the device screen's width and height. Afterwards just resize the canvas accordingly in your Javascript. Example:

var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var height = (window.innerHeight > 0) ? window.innerHeight : screen.height;
var canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;

You might have screens with varying resolution ratios though, what I usually do in this case is calculate your original width's and the device's width ratio and then adjust both width and height accordingly with that value. Example:

var originalWidth = 960;  //Example value
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var widthRatio = originalWidth / width;
canvas.width *= widthRatio;
canvas.height *= widthRatio;

This usually works fine for me on any device, hope this helps.


I know it's been a while but i found an easier way to do it using the zoom feature.

This code is triggered when the window resize is completed. It allows me to determine based on the new dimension, the zoom factor needed to resize everything in the canvas.

function rescale_canvas_if_needed()
{
	var optimal_dimensions = get_optimal_canvas_dimensions();
	var scaleFactor=optimal_dimensions[0]/wpd.canvas_w;
	if(scaleFactor != 1) {
		wpd_editor.canvas.setWidth(optimal_dimensions[0]);
		wpd_editor.canvas.setHeight(optimal_dimensions[1]);
		wpd_editor.canvas.setZoom(scaleFactor);
		wpd_editor.canvas.calcOffset();
		wpd_editor.canvas.renderAll();
  }
}

$( window ).resize(function() {
	clearTimeout(resizeId);
	resizeId = setTimeout(handle_resize, 500);
 });
 
 function handle_resize()
 {
	$(".canvas-container").hide();
	rescale_canvas_if_needed();
	$(".canvas-container").show();               
	 
 }