How can an object be constrained to being resized/scaled only within the bounds of the canvas (or another object in my case) when using Fabric.js?
Currently, I'm handling the object:scaling
event:
// 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 The BoundsHelper
class is just a helper for wrapping up the math of calculating the right/bottom sides of the 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 make use of the onBeforeScaleRotate
callback to disable the scaling lock added by the above:
onObjectBeforeScaleRotate = (targetObject: fabric.IObject): boolean => {
targetObject.lockScalingX = targetObject.lockScalingY = false;
return true;
}
The issue I observe is that it seems like Fabric doesn't redraw the object fast enough for me to accurately detect that scale is passing the image's boundary. In other words, if I scale slowly, then life is good; if I scale quickly, then I can scale outside of the image's bounds.