当包含的对象改变大小时,Fabric.js 自动调整组大小

Posted

技术标签:

【中文标题】当包含的对象改变大小时,Fabric.js 自动调整组大小【英文标题】:Fabric.js auto-size group controls when contained objects change size 【发布时间】:2014-11-06 00:47:15 【问题描述】:

当我有一组织物 IText 对象并一起更改它们的所有字体大小时,分组的文本对象都会根据字体大小缩小或增大,但组控件和边框保持原位而不是大小也发生变化.我的问题是,如何在更改组内的对象后让组控件自动调整大小?

查看 Fabric 的代码,我无法弄清楚组的边界是如何设置的。我曾尝试在组上调用 _setCoords()setCoords(),但这会将组移动到画布上的 0、0 并保持高度和宽度相同。调用_setCoords(true) 无效。

我还尝试了以下代码,其中我尝试将旧组替换为包含相同对象的新组,理论上这会划定新边界,但这似乎是一个笨拙的解决方案。此外,它不起作用:新的组边界和控件不会出现。

var selected = [];
var all = scope.canvas.getObjects();
for(var x in all) 
    if(all.active) 
        selected[selected.length] = x;
    

scope.canvas._discardActiveGroup();
var objects = [];
for(var x in selected) 
    objects[x] = scope.canvas.getObjects()[x];

var group = new fabric.Group(objects,
    originX: 'center',
    originY: 'center',
    canvas: scope.canvas
);

//Using $timeout so that this will wait until current $scope digest is finished
$timeout(function () 
    scope.canvas.setActiveGroup(group);
    scope.canvas.renderAll();
, 0);
scope.canvas.renderAll();

编辑:

我认为这与另一个问题有关,即在文本对象因字体大小更改而更改大小后,其选择区域仍保持在大小更改之前的位置。也就是说,如果您在预调整大小的边界矩形内单击,它会选择对象,而不管调整后的边界矩形如何。只有在选择了一些其他对象或取消选择所有对象后,选择才能按预期对对象进行。我为对象调用setCoords(),因此它们的边界绘制正确。

【问题讨论】:

【参考方案1】:

正如我在编辑问题时所说,这个问题有两个部分。解决我的问题需要以下两种解决方案。

错误 #1: 即使您使用 setCoords(),IText 对象的选择区域仍保持大小更改之前的状态。这是因为setCoords()“根据当前角度、宽度和高度设置角位置坐标”——但它不会根据文本的更改来更新宽度和高度。这只发生在方法_renderViaNative(ctx):

//inside _renderViaNative:
this.width = this._getTextWidth(ctx, textLines);
this.height = this._getTextHeight(ctx, textLines);

解决方案:因为我实际上使用的是自定义的 IText 降级类,所以我使用了 setCoords 函数的覆盖来修复它。像这样的覆盖应该是 IText 类的一部分:

/** @Override */
setCoords : function () 
    var ctx = this.canvas.getContext();
    var textLines = this.text.split(this._reNewline);
    this._setTextStyles(ctx);
    this.width = this._getTextWidth(ctx, textLines);
    this.height = this._getTextHeight(ctx, textLines);
    this.callSuper('setCoords');
,

错误 #2: 组的选择区域在其包含的 IText 对象更改大小后不会刷新,即使您调用 setCoords。如果您使用 false 参数调用_calcBounds,它会通过计算对象的中心点来设置组的中心点——但是由于对象已被重置为相对于组中心的坐标为它们的 (0,0),重新计算以 (0,0) 为中心,因此,整个组移动,使其中心位于画布上的 (0,0)。如果您使用 true 参数调用 _calcBounds,它将围绕其原始中心而不是围绕新中心调整大小,并且您不能手动重置中心,因为这也会使对象移动。

解决方案:通过重置对象的坐标从头开始重新计算边界。我主要是通过蚕食函数addWithUpdate(object)来做到这一点的。

// set the objects to their not-in-group coordinates
activeGroup.destroy(); 
// since _restoreObjectsState (inside destroy) set objects inactive, set them active
activeGroup.forEachObject(activeGroup._setObjectActive, activeGroup);
// now we can call _calcBounds without bouncing the group to 0,0
activeGroup._calcBounds();
// set the objects to their in-group coordinates
activeGroup._updateObjectsCoords();

【讨论】:

以上是关于当包含的对象改变大小时,Fabric.js 自动调整组大小的主要内容,如果未能解决你的问题,请参考以下文章

Fabric.js 逐像素操作 Image 对象以改变颜色

Fabric.js 逐像素操作 Image 对象以改变颜色

Fabric js:使用鼠标调整大小时增加字体大小而不是仅仅缩放

在 Fabric.js 中将对象添加到画布时设置对象的位置

从 Fabric.js 中的 JSON 加载加载默认属性

Angular.js 和 Fabric.js:一旦代码移动到 Angular 指令,Fabric 画布就会改变行为