mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-04-10 17:30:59 +00:00
229 lines
No EOL
5.6 KiB
JavaScript
229 lines
No EOL
5.6 KiB
JavaScript
//= require "path.class"
|
|
|
|
(function(){
|
|
|
|
var fabric = this.fabric || (this.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.originalState = { };
|
|
this.paths = paths;
|
|
|
|
this.setOptions(options);
|
|
this.initProperties();
|
|
|
|
this.setCoords();
|
|
|
|
if (options.sourcePath) {
|
|
this.setSourcePath(options.sourcePath);
|
|
}
|
|
},
|
|
|
|
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);
|
|
},
|
|
|
|
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();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @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;
|
|
},
|
|
|
|
/**
|
|
* @method toObject
|
|
* @return {Object} object representation of an instance
|
|
*/
|
|
toObject: function() {
|
|
return extend(parentToObject.call(this), {
|
|
paths: invoke(this.getObjects(), 'clone'),
|
|
sourcePath: this.sourcePath
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @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 an object
|
|
* @method toString
|
|
* @return {String} string representation of an object
|
|
*/
|
|
toString: function() {
|
|
return '#<fabric.PathGroup (' + this.complexity() +
|
|
'): { top: ' + this.top + ', left: ' + this.left + ' }>';
|
|
},
|
|
|
|
/**
|
|
* @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;
|
|
},
|
|
|
|
/**
|
|
* @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;
|
|
}
|
|
|
|
/**
|
|
* @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);
|
|
};
|
|
})(); |