繁体   English   中英

Fabric.js - 约束调整大小/缩放到Canvas / Object

[英]Fabric.js - Constrain Resize/Scale to Canvas/Object

在使用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不能足够快地重绘对象,以便我准确地检测到比例正在通过图像的边界。 换句话说,如果我慢慢扩展,那么生活就是好的; 如果我快速缩放,那么我可以在图像边界之外缩放。

这不是关于速度。 事件是您使用鼠标执行某些操作的离散采样。 即使您虚拟地逐像素移动,鼠标也有自己的采样率,并且当您快速移动时,javascript事件不会触发您移动的每个像素。

因此,如果您在克服限制时限制应用程序停止缩放,当您克服此限制时,您将停止缩放,在限制之后的某个像素,仅仅因为最后一次检查您在绑定前是1像素,在您是10之后的事件它之后的像素。

我改变了代码,这根本不是完美的,但是让你有机会处理这个问题。

当您克服限制时,而不是锁定缩放,计算图像内部的正确缩放并应用该比例。

当你完全处于图像之外时,这个逻辑会出现问题,因此我已将rect放入其中,只是为了演示不同的方法。

 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> 

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;
  }

其他,你应该更新到最新版本

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM