fabric.js/src/path_group.class.js

245 lines
No EOL
6.3 KiB
JavaScript

//= require "path.class"
(function(global) {
"use strict";
var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend,
invoke = fabric.util.array.invoke,
parentSet = fabric.Object.prototype.set,
parentToObject = fabric.Object.prototype.toObject,
camelize = fabric.util.string.camelize,
capitalize = fabric.util.string.capitalize;
if (fabric.PathGroup) {
fabric.warn('fabric.PathGroup is already defined');
return;
}
/**
* @class PathGroup
* @extends fabric.Path
*/
fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @scope fabric.PathGroup.prototype */ {
/**
* @property
* @type String
*/
type: 'path-group',
/**
* @property
* @type Boolean
*/
forceFillOverwrite: false,
/**
* Constructor
* @method initialize
* @param {Array} paths
* @param {Object} [options] Options object
* @return {fabric.PathGroup} thisArg
*/
initialize: function(paths, options) {
options = options || { };
this.paths = paths;
this.setOptions(options);
//this._initProperties();
this.setCoords();
if (options.sourcePath) {
this.setSourcePath(options.sourcePath);
}
},
/**
* @private
* @method _initProperties
*/
// _initProperties: function() {
// this.stateProperties.forEach(function(prop) {
// if (prop === 'fill') {
// this.set(prop, this.options[prop]);
// }
// else if (prop === 'angle') {
// this.setAngle(this.options[prop]);
// }
// else {
// this[prop] = this.options[prop];
// }
// }, this);
// },
/**
* Renders this group on a specified context
* @method render
* @param {CanvasRenderingContext2D} ctx Context to render this instance on
*/
render: function(ctx) {
if (this.stub) {
// fast-path, rendering image stub
ctx.save();
this.transform(ctx);
this.stub.render(ctx, false /* no transform */);
if (this.active) {
this.drawBorders(ctx);
this.drawCorners(ctx);
}
ctx.restore();
}
else {
ctx.save();
var m = this.transformMatrix;
if (m) {
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
this.transform(ctx);
for (var i = 0, l = this.paths.length; i < l; ++i) {
this.paths[i].render(ctx, true);
}
if (this.active) {
this.drawBorders(ctx);
this.hideCorners || this.drawCorners(ctx);
}
ctx.restore();
}
},
/**
* Sets certain property to a certain value
* @method set
* @param {String} prop
* @param {Any} value
* @return {fabric.PathGroup} thisArg
*/
set: function(prop, value) {
if ((prop === 'fill' || prop === 'overlayFill') && this.isSameColor()) {
this[prop] = value;
var i = this.paths.length;
while (i--) {
this.paths[i].set(prop, value);
}
}
else {
// skipping parent "class" - fabric.Path
parentSet.call(this, prop, value);
}
return this;
},
/**
* Returns object representation of this path group
* @method toObject
* @return {Object} object representation of an instance
*/
toObject: function() {
return extend(parentToObject.call(this), {
paths: invoke(this.getObjects(), 'clone'),
sourcePath: this.sourcePath
});
},
/**
* Returns dataless object representation of this path group
* @method toDatalessObject
* @return {Object} dataless object representation of an instance
*/
toDatalessObject: function() {
var o = this.toObject();
if (this.sourcePath) {
o.paths = this.sourcePath;
}
return o;
},
/**
* Returns a string representation of this path group
* @method toString
* @return {String} string representation of an object
*/
toString: function() {
return '#<fabric.PathGroup (' + this.complexity() +
'): { top: ' + this.top + ', left: ' + this.left + ' }>';
},
/**
* Returns true if all paths in this group are of same color
* @method isSameColor
* @return {Boolean} true if all paths are of the same color (`fill`)
*/
isSameColor: function() {
var firstPathFill = this.getObjects()[0].get('fill');
return this.getObjects().every(function(path) {
return path.get('fill') === firstPathFill;
});
},
/**
* Returns number representation of object's complexity
* @method complexity
* @return {Number} complexity
*/
complexity: function() {
return this.paths.reduce(function(total, path) {
return total + ((path && path.complexity) ? path.complexity() : 0);
}, 0);
},
/**
* Makes path group grayscale
* @method toGrayscale
* @return {fabric.PathGroup} thisArg
*/
toGrayscale: function() {
var i = this.paths.length;
while (i--) {
this.paths[i].toGrayscale();
}
return this;
},
/**
* Returns all paths in this path group
* @method getObjects
* @return {Array} array of path objects included in this path group
*/
getObjects: function() {
return this.paths;
}
});
/**
* @private
* @method instantiatePaths
*/
function instantiatePaths(paths) {
for (var i = 0, len = paths.length; i < len; i++) {
if (!(paths[i] instanceof fabric.Object)) {
var klassName = camelize(capitalize(paths[i].type));
paths[i] = fabric[klassName].fromObject(paths[i]);
}
}
return paths;
}
/**
* Creates fabric.Triangle instance from an object representation
* @static
* @method fabric.PathGroup.fromObject
* @param {Object} object
* @return {fabric.PathGroup}
*/
fabric.PathGroup.fromObject = function(object) {
var paths = instantiatePaths(object.paths);
return new fabric.PathGroup(paths, object);
};
})(this);