C. Ovidiu
C. Ovidiu

Reputation: 1134

CSS & Fabric js: Scale canvas and objects on small resolutions

I am working with fabricjs for an application. On mobile I need to scale the whole canvas down so it can fit the screen.

The issue is that on the canvas there are 10 objects in total, between images, texts and fabric js background objects.

I tried scaling the whole canvas using CSS transform and it seems to work, but the whole area gets smaller, as in this picture enter image description here

The original canvas is the entire picture, but when I apply the transform, the canvas becomes the red area, and when moving objects with fabricjs, they get clipped when outside the red area.

Is there any way to fix this in CSS ? edit Basically I need to scale everything inside the canvas, but the canvas itself needs to always be 100% in height and with of the current window.

Or is there any way to resize the whole canvas with all the objects ? I also tried fabric js setZoom() method, but it gets even more messed up.

Thank you

Upvotes: 3

Views: 3265

Answers (2)

A-Diddy
A-Diddy

Reputation: 632

Possible Duplicate: Scale fabric.js canvas objects

It seems Fabric.js doesn't support this natively... at least, I haven't found the options to do it.

Until Fabric.js provides this, the best way may be to iterate through the objects and scale them manually to match the new screen size based on the ratio of the previous screen size. For example...

const canvas = new fabric.Canvas({});
let prevScreenWidth = window.innerWidth;
let prevScreenHeight = window.innerHeight;

window.addEventListener('resize', handleResize());

/*********************************************************
 * Get the new screen size ratio in relation to the previous screen size
 * to determine the scale factor.
 *********************************************************/
function handleResize() {
  // Error Handling: Make sure the scale ratio denominator is defined.
  prevScreenWidth = prevScreenWidth || window.innerWidth;
  prevScreenHeight = prevScreenHeight || window.innerHeight;

  // Get the current/new screen width and height (scale ratio numerator).
  const currScreenWidth = window.innerWidth;
  const currScreenHeight = window.innerHeight;

  // Determine width and height scale ratios
  const widthRatio = currScreenWidth / prevScreenWidth;
  const heightRatio = currScreenHeight / prevScreenHidth;

  // Get the average of the width and height scale ratios
  const scaleFactor = (widthRatio + heightRatio) / 2;

  // Scale the objects with the screen size adjustment ratio average as the scale factor 
  scaleObjects(scaleFactor);

  // Record the current screen sizes to be used for the next resize.
  prevScreenWidth = window.innerWidth;
  prevScreenHeight = window.innerHeight;
}


/*********************************************************
 * Iterate through each object and apply the same scale factor to each one.
 *********************************************************/
function scaleObjects(factor) {
  // Set canvas dimensions (this could be skipped if canvas resizes based on CSS).
  canvas.setDimensions({
    width: canvas.getWidth() * factor, 
    height: canvas.getHeight() * factor 
  });

  if (canvas.backgroundImage) {
    // Need to scale background images as well
    const bi = canvas.backgroundImage;
    bi.width = bi.width * factor; bi.height = bi.height * factor;
  }

  const objects = canvas.getObjects();

  for (let i in objects) {
    const scaleX = objects[i].scaleX;
    const scaleY = objects[i].scaleY;
    const left = objects[i].left;
    const top = objects[i].top;

    const tempScaleX = scaleX * factor;
    const tempScaleY = scaleY * factor;
    const tempLeft = left * factor;
    const tempTop = top * factor;

    objects[i].scaleX = tempScaleX;
    objects[i].scaleY = tempScaleY;
    objects[i].left = tempLeft;
    objects[i].top = tempTop;

    objects[i].setCoords();
  }
  canvas.renderAll();
  canvas.calcOffset();
}

See this previous answer for more information on the scaleObjects() method... Scale fabric.js canvas objects

Upvotes: 1

AndreaBogazzi
AndreaBogazzi

Reputation: 14731

The best way is find a scale ratio that fit your screen (is unclear how you plan to fit a square canvas on a long screen).

Then leave the css untrasformed. ratio is the scale ratio that fit the canvas in screen;

resize the canvas to actual screen dimensions:

canvas.setDimensions({ width: originalWidth * ratio, height: originalHeight * ratio });
canvas.setZoom(ratio)

This should give you a smaller canvas with everything in place.

Upvotes: 1

Related Questions