在使用Fabric.js时,如何将对象限制为仅在画布(或我的情况下的其他对象)的范围内调整大小/缩放?
目前,我正在处理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;
}
**编辑BoundsHelper
类只是一个帮助,用于包装计算对象边界框右侧/底侧的数学运算。
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;
我还使用onBeforeScaleRotate
回调来禁用上面添加的缩放锁定:
onObjectBeforeScaleRotate = (targetObject: fabric.IObject): boolean => {
targetObject.lockScalingX = targetObject.lockScalingY = false;
return true;
}
我观察到的问题是,Fabric似乎没有足够快地重新绘制对象,以便我能够准确地检测到比例正在通过图像的边界。换句话说,如果我慢慢扩展,那么生活就是好的;如果我快速缩放,那么我可以在图像边界之外缩放。
答案 0 :(得分:2)
这与速度无关。 事件是您使用鼠标执行某些操作的离散采样。 即使您虚拟地逐像素移动,鼠标也有自己的采样率,并且当您快速行动时,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();
&#13;
img {
display: none;
}
canvas {
border: solid black 1px;
}
&#13;
<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>
&#13;
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;
}
其他,您应该更新到最新版本