FabricJS |如果包含对象更改大小,如何调整Fabric.Group的大小

时间:2015-03-10 12:28:16

标签: javascript fabricjs

我有一个基于fabric.Group的Custom对象(fabric.DefaultSensorGroup)。此自定义对象包含fabric.Text和各种其他自定义对象(fabric.DefaultSensor)。

如果我向组中添加/删除对象,则该组的“边框”不会根据包含的对象调整大小。

DefaultSensor:

fabric.DefaultSensor = fabric.util.createClass(fabric.Group, {
    type : 'defaultSensor',

    initialize : function(options) {
        options || (options = {});

        // rect base
        var rectBase = new fabric.Rect({
            left : 0,
            top : 0,
            fill : options.sensorFillColor || '#aaf',
            width : 350,
            height : 30,
            stroke : '#000',
            strokeWidth : 1,
            rx : 5,
            ry : 5,
            shadow : 'rgba(0,0,0,1) 3px 3px 3px'
        });

        // text for sensor name and unit
        var nameUnitText = new fabric.Text('n/a', {
            left : 5,
            top : 2,
            fontSize : 20,
            fontFamily : 'Arial'
        });

        // text for sensor value
        var valueText = new fabric.Text('n/a', {
            top : 2,
            fontSize : 20,
            fontFamily : 'Arial',
        });

        this.callSuper('initialize', [ rectBase, nameUnitText, valueText ],
                options);

        this.set('sensorId', options.sensorId || '');
        this.set('sensorName', options.sensorName || 'n/a');
        this.set('sensorNameFontSize', options.sensorNameFontSize || 20);
        this.set('dataSeriesName', options.dataSeriesName || 'n/a');
        this.set('sensorUnit', options.sensorUnit || 'n/a');
        this.set('sensorValue', options.sensorValue || 'n/a');
        this.set('sensorFillColor', options.sensorFillColor || '#aaf');
        this.set('sensorDeviceId', options.sensorDeviceId || '');
        this.set('sensorProjectId', options.sensorProjectId || '');
        this.set('sensorDataSeriesId', options.sensorDataSeriesId || '');
        this.set('fractionalDigits', options.fractionalDigits || 2);
    },

    render : function(ctx, noTransform) {
        this.refreshSensorData();
        this.callSuper('render', ctx, noTransform);
    },

    refreshSensorData : function() {
        // set fill of base rect
        this.getObjects()[0].set('fill', this.get('sensorFillColor'));

        // set sensor name and unit text from current values
        this.getObjects()[1].set('text', this.get('dataSeriesName') + ' ['
                + this.get('sensorUnit') + ']');

        // set sensor name and unit text from current values
        this.getObjects()[1].set('fontSize', this.get('sensorNameFontSize'));

        // set sensor value text from current value
        this.getObjects()[2].set('text', this.get('sensorValue') + '');

        // set new width of base rect arcording to content width + 30 padding
        this.getObjects()[0].set('width', this.getObjects()[1].get('width')
                + this.getObjects()[2].get('width') + 30);

        // align base rect according to new width
        this.getObjects()[0].set('left', -1 * this.getObjects()[0].get('width')
                / 2);
        this.getObjects()[0].set('top', -1 * this.getObjects()[0].get('height')
                / 2);

        // adapt group width according to new content width
        this.set('width', this.getObjects()[0].get('width'));
        this.setCoords();

        // set new left of sensorlabel + 3 padding
        this.getObjects()[1].set('left', (-1 * (this.getObjects()[0]
                .get('width') / 2)) + 3);

        var topPadding = (this.getObjects()[0].get('height') - this
                .getObjects()[1].get('height')) / 2;
        this.getObjects()[1].set('top', (-1 * (this.getObjects()[0]
                .get('height') / 2))
                + topPadding);

        // position sensor value text according to the text width (right
        // aligned)
        this.getObjects()[2].set('left',
                (this.getObjects()[0].get('width') / 2)
                        - this.getObjects()[2].get('width') - 5);

    },

    toObject : function() {
        return fabric.util.object.extend(this.callSuper('toObject'), {
            sensorId : this.get('sensorId'),
            sensorName : this.get('sensorName'),
            sensorNameFontSize : this.get('sensorNameFontSize'),
            sensorContainerWidth : this.get('sensorContainerWidth'),
            dataSeriesName : this.get('dataSeriesName'),
            sensorUnit : this.get('sensorUnit'),
            sensorValue : this.get('sensorValue'),
            sensorFillColor : this.get('sensorFillColor'),
            sensorDeviceId : this.get('sensorDeviceId'),
            sensorProjectId : this.get('sensorProjectId'),
            sensorDataSeriesId : this.get('sensorDataSeriesId'),
            fractionalDigits : this.get('fractionalDigits')
        });
    },

    _render : function(ctx) {
        this.callSuper('_render', ctx);
    }
});

fabric.DefaultSensor.fromObject = function(object, callback) {
    fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
        delete object.objects;
        callback && callback(new fabric.DefaultSensor(object));
    });
};

fabric.DefaultSensor.selected = function(object) {
    detailsbar.addColorSetter(object, 'sensorFillColor', webLU.gs(
            'label.Color', 'Color'));
    detailsbar.addOpacitySetter(object, 'opacity', webLU.gs('label.Opacity',
            'Opacity'));
    detailsbar.addSensorSelectSetter(object, webLU.gs('label.SensorSelection',
            'Sensor selection'));
    detailsbar.addDecimalPlacesSetter(object, 'fractionalDigits', webLU.gs(
            'label.DecimalPlaces', 'Decimal places'));
    detailsbar.addRangeSetter(object, 'sensorNameFontSize', webLU.gs(
            'label.SensorNameFontSize', 'Sensorname Font Size'), 10, 20);

};

fabric.DefaultSensor.async = true;

DefaultSensorGroup:

fabric.DefaultSensorGroup = fabric.util.createClass(fabric.Group,
{
    type : 'defaultSensorGroup',

    groupWidth: 40,

    groupHeight : 50,

    initialize : function(objects, options)
    {
        options || (options =
        {});

        var objectsExtended = this.buildGraphicObjects(objects)

        this.callSuper('initialize', objectsExtended, options);
        this.set('sensorGroupName', options.sensorGroupName || 'undefinedSensorGroup');
        this.set('sensorSelection', objects || []);
        this.set('fractionalDigits', options.fractionalDigits || 2);

    var blub = this.getObjects();
    for(var i in blub) {
        this.groupWidth = Math.max(this.groupWidth, blub[i].get('width'));
        this.groupHeight = Math.max(this.groupHeight, blub[i].get('height'));
    }

    this.setWidth(this.groupWidth);
        this.setHeight(this.groupHeight);
    },

    buildGraphicObjects : function(objects)
    {
        // rect base
        var rectBase = new fabric.Rect(
        {
            left : 0,
            top : 0,
            fill : '#C0C0C0',
            width : 370,
            height : 40 + (objects.length * 35),
            stroke : '#000',
            strokeWidth : 1,
            rx : 5,
            ry : 5,
            shadow : 'rgba(0,0,0,1) 3px 3px 3px'
        });

        // group name text
        var groupNameText = new fabric.Text('n/a',
        {
            left : 5,
            top : 0,
            fontSize : 20,
            textAlign : 'center',
            fontFamily : 'Arial'
        });

        var objectsExtended = [ groupNameText ];

        var sensorTopPosition = groupNameText.getHeight() + groupNameText.getLeft();

        // extend sensor group base objects (rect and group name text) with
        // sensor objects and set position of sensor objects
        if (objects)
        {
            for (var i = 0; i < objects.length; i++)
            {
                objectsExtended.push(objects[i].set(
                {
                    left : 10,
                    top : sensorTopPosition
                }));
                sensorTopPosition += objects[i].getHeight();
            }
        }

        return objectsExtended;
    },

    render : function(ctx, noTransform)
    {
        this.refreshGroupData();
        this.callSuper('render', ctx, noTransform);
    },

    refreshGroupData : function()
    {
        this.getObjects()[0].set('text', this.get('sensorGroupName'));
    },

    toObject : function()
    {
        return fabric.util.object.extend(this.callSuper('toObject'),
        {
            sensorGroupName : this.get('sensorGroupName'),
            sensorSelection : this.get('sensorSelection'),
            fractionalDigits : this.get('fractionalDigits')
        });
    },

    addSensorToSelection : function(fabricSensor)
    {
        fabricSensor.set('fractionalDigits', this.get('fractionalDigits'));
        this.get('sensorSelection').push(fabricSensor);
        this.initialize(this.get('sensorSelection'), this.toObject());
    },

    removeSensorFromSelection : function(index)
    {
        this.get('sensorSelection').splice(index, 1);
        this.initialize(this.get('sensorSelection'), this.toObject());
    },

    _render : function(ctx)
    {
        this.callSuper('_render', ctx);
    }
});

fabric.DefaultSensorGroup.fromObject = function(object, callback)
{
    fabric.util.enlivenObjects(object.objects, function(enlivenedObjects)
    {
        delete object.objects;
        var sensors = [];
        if (object.sensorSelection)
        {
            for (var i = 0; i < object.sensorSelection.length; i++)
            {
                sensors.push(new fabric.DefaultSensor(object.sensorSelection[i]).set('fractionalDigits', object.fractionalDigits));
            }
        }
        callback && callback(new fabric.DefaultSensorGroup(sensors, object));
    });
};

fabric.DefaultSensorGroup.selected = function(object)
{
    detailsbar.addTextSetter(object, 'sensorGroupName', webLU.gs('label.Name', 'Name'));
    detailsbar.addOpacitySetter(object, 'opacity', webLU.gs('label.Opacity', 'Opacity'));
    detailsbar.addSensorGroupSensorSelectionSetter(object, webLU.gs('label.SensorSelection', 'Sensor selection'));
    detailsbar.addDecimalPlacesSetter(object, 'fractionalDigits', webLU.gs('label.DecimalPlaces', 'Decimal places'));
};

fabric.DefaultSensorGroup.async = true;

enter image description here

1 个答案:

答案 0 :(得分:1)

添加对象时,是否使用group.add()或group.addWithUpdate()添加它们?

将add函数抛入组中而不重新计算新的边框大小。但是使用group.addWithUpdate(),它会重新调整组的边界框的大小。