Fabric.js - Constray Resize / Scale to Canvas / Object

How can I restrict an object to change / scale only within the canvas (or another object in my case) when using Fabric.js?

I am currently processing an event object:scaling:

// Typescript being used; 

onObjectScaling = (event): boolean => {
    // Prevent scaling object outside of image

    var object = <fabric.IObject>event.target;
    var objectBounds: BoundsHelper;
    var imageBounds: BoundsHelper;

    object.setCoords();
    objectBounds = new BoundsHelper(object);
    imageBounds = new BoundsHelper(this.imageManipulatorContext.getImageObject());

    if (objectBounds.left < imageBounds.left || objectBounds.right > imageBounds.right) {
        console.log('horizontal bounds exceeded');
        object.scaleX = this.selectedObjectLastScaleX;
        object.lockScalingX = true;
        object.setCoords();
    } else {
        this.selectedObjectLastScaleX = object.scaleX;
    }

    if (objectBounds.top < imageBounds.top || objectBounds.bottom > imageBounds.bottom) {
        console.log('vertical bounds exceeded');
        object.scaleY = this.selectedObjectLastScaleY;
        object.lockScalingY = true;
        object.setCoords();
    } else {
        this.selectedObjectLastScaleY = object.scaleY;
    }

    return true;
}

** edit A class BoundsHelperis just a math calculator for calculating the right / bottom sides of a bounding box for an object.

import fabric = require('fabric');

class BoundsHelper {
    private assetRect: { left: number; top: number; width: number; height: number; };

    get left(): number { return this.assetRect.left; }
    get top(): number { return this.assetRect.top; }
    get right(): number { return this.assetRect.left + this.assetRect.width; }
    get bottom(): number { return this.assetRect.top + this.assetRect.height; }

    get height(): number { return this.assetRect.height; }
    get width(): number { return this.assetRect.width; }

    constructor(asset: fabric.IObject) {
        this.assetRect = asset.getBoundingRect();
    }
}

export = BoundsHelper;

I also use a callback onBeforeScaleRotateto disable the zoom lock added above:

onObjectBeforeScaleRotate = (targetObject: fabric.IObject): boolean => {
    targetObject.lockScalingX = targetObject.lockScalingY = false;

    return true;
}

, , , , Fabric , , . , , ; , .

+4
1

. - , . , , javascript , , .

, , , , , , , 1 , 10 .

, , .

, , .

, , , .

var BoundsHelper = (function () {
  function BoundsHelper(asset) {
    this.assetRect = asset.getBoundingRect();
  }
  Object.defineProperty(BoundsHelper.prototype, "left", {
    get: function () {
      return this.assetRect.left;
    },
    enumerable: true,
    configurable: true
  });
  Object.defineProperty(BoundsHelper.prototype, "top", {
    get: function () {
      return this.assetRect.top;
    },
    enumerable: true,
    configurable: true
  });
  Object.defineProperty(BoundsHelper.prototype, "right", {
    get: function () {
      return this.assetRect.left + this.assetRect.width;
    },
    enumerable: true,
    configurable: true
  });
  Object.defineProperty(BoundsHelper.prototype, "bottom", {
    get: function () {
      return this.assetRect.top + this.assetRect.height;
    },
    enumerable: true,
    configurable: true
  });

  Object.defineProperty(BoundsHelper.prototype, "height", {
    get: function () {
      return this.assetRect.height;
    },
    enumerable: true,
    configurable: true
  });
  Object.defineProperty(BoundsHelper.prototype, "width", {
    get: function () {
      return this.assetRect.width;
    },
    enumerable: true,
    configurable: true
  });
  return BoundsHelper;
})();

////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

var canvas = new fabric.Canvas('c');
var rectangle = new fabric.Rect({
	fill: 'black',
  originX: 'left',
  originY: 'top',
  stroke: 'false',
  opacity: 1,
  left: 180,
  top: 180,
  height: 50,
  width: 50
});
var rectangleBounds = new BoundsHelper(rectangle);
var image = new fabric.Image(i, {
	selectable: false,
  borderColor: 'black',
  width: 200,
  height: 200
});

canvas.on("object:scaling", function (event) {
  var object = event.target;
  var objectBounds = null;
  var imageBounds = null;
  var desiredLength;
  object.setCoords();
  objectBounds = new BoundsHelper(object);
  imageBounds = new BoundsHelper(image);

  if (objectBounds.left < imageBounds.left) {
    object.lockScalingX = true;
    // now i have to calculate the right scaleX factor.
    desiredLength =objectBounds.right -  imageBounds.left;
    object.scaleX = desiredLength / object.width;
  }

  if (objectBounds.right > imageBounds.right) {
   object.lockScalingX = true;
    desiredLength = imageBounds.right - objectBounds.left;
    object.scaleX = desiredLength / object.width;
  }


  if (objectBounds.top < imageBounds.top) { 
   object.lockScalingY = true;
    desiredLength = objectBounds.bottom - imageBounds.top;
    object.scaleY = desiredLength / object.height;
  }

  if (objectBounds.bottom > imageBounds.bottom) {
    object.lockScalingY = true;
    desiredLength = imageBounds.bottom - objectBounds.top;
    object.scaleY = desiredLength / object.height;
  }

return true;
});

canvas.onBeforeScaleRotate = function (targetObject) {
  targetObject.lockScalingX = targetObject.lockScalingY = false;

  return true;
};

canvas.on('after:render', function() {
  canvas.contextContainer.strokeStyle = '#555';

  var bound = image.getBoundingRect();

  canvas.contextContainer.strokeRect(
    bound.left + 0.5,
    bound.top + 0.5,
    bound.width,
    bound.height
  );
});

canvas.add(image);
canvas.centerObject(image);
image.setCoords();
canvas.add(rectangle);
canvas.renderAll();
img {
  display: none;
}

canvas {
  border: solid black 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.12/fabric.min.js"></script>
<img id="i" src="http://fabricjs.com/assets/ladybug.png" />
<canvas id="c" width="500" height="500"></canvas>
Hide result

https://jsfiddle.net/84zovnek/2/

  if (objectBounds.left < imageBounds.left) {
    //object.lockScalingX = true;
    // now i have to calculate the right scaleX factor.
    desiredLength = imageBounds.left - objectBounds.right;
    object.scaleX = desiredLength / object.width;
  }

,

+2

Source: https://habr.com/ru/post/1623145/


All Articles