2012-12-02 04:04:10 +08:00
|
|
|
(function() {
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
2012-12-02 04:04:10 +08:00
|
|
|
* Container constructor. Containers are used to contain nodes or other containers
|
|
|
|
* @constructor
|
|
|
|
* @augments Kinetic.Node
|
|
|
|
* @param {Object} config
|
2013-01-27 12:42:19 +08:00
|
|
|
* {{NodeParams}}
|
2013-02-16 10:20:34 +08:00
|
|
|
* {{ContainerParams}}
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Container = function(config) {
|
|
|
|
this._containerInit(config);
|
|
|
|
};
|
2012-11-14 16:18:49 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Container.prototype = {
|
|
|
|
_containerInit: function(config) {
|
|
|
|
this.children = [];
|
|
|
|
Kinetic.Node.call(this, config);
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get children
|
|
|
|
* @name getChildren
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
*/
|
|
|
|
getChildren: function() {
|
|
|
|
return this.children;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* remove all children
|
|
|
|
* @name removeChildren
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
*/
|
|
|
|
removeChildren: function() {
|
|
|
|
while(this.children.length > 0) {
|
|
|
|
this.children[0].remove();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* add node to container
|
|
|
|
* @name add
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {Node} child
|
|
|
|
*/
|
|
|
|
add: function(child) {
|
|
|
|
var go = Kinetic.Global, children = this.children;
|
|
|
|
child.index = children.length;
|
|
|
|
child.parent = this;
|
|
|
|
children.push(child);
|
|
|
|
|
|
|
|
// chainable
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* return an array of nodes that match the selector. Use '#' for id selections
|
|
|
|
* and '.' for name selections
|
|
|
|
* ex:
|
|
|
|
* var node = stage.get('#foo'); // selects node with id foo
|
|
|
|
* var nodes = layer.get('.bar'); // selects nodes with name bar inside layer
|
|
|
|
* @name get
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {String} selector
|
|
|
|
*/
|
|
|
|
get: function(selector) {
|
|
|
|
var collection = new Kinetic.Collection();
|
|
|
|
// ID selector
|
|
|
|
if(selector.charAt(0) === '#') {
|
|
|
|
var node = this._getNodeById(selector.slice(1));
|
|
|
|
if(node) {
|
|
|
|
collection.push(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// name selector
|
|
|
|
else if(selector.charAt(0) === '.') {
|
|
|
|
var nodeList = this._getNodesByName(selector.slice(1));
|
|
|
|
Kinetic.Collection.apply(collection, nodeList);
|
|
|
|
}
|
|
|
|
// unrecognized selector, pass to children
|
|
|
|
else {
|
|
|
|
var retArr = [];
|
|
|
|
var children = this.getChildren();
|
|
|
|
var len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
|
|
|
retArr = retArr.concat(children[n]._get(selector));
|
|
|
|
}
|
|
|
|
Kinetic.Collection.apply(collection, retArr);
|
|
|
|
}
|
|
|
|
return collection;
|
|
|
|
},
|
|
|
|
_getNodeById: function(key) {
|
2013-01-14 03:10:49 +08:00
|
|
|
var stage = this.getStage(), go = Kinetic.Global, node = go.ids[key];
|
|
|
|
if(node !== undefined && this.isAncestorOf(node)) {
|
|
|
|
return node;
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
_getNodesByName: function(key) {
|
2013-01-14 03:10:49 +08:00
|
|
|
var go = Kinetic.Global, arr = go.names[key] || [];
|
2012-12-02 04:04:10 +08:00
|
|
|
return this._getDescendants(arr);
|
|
|
|
},
|
|
|
|
_get: function(selector) {
|
|
|
|
var retArr = Kinetic.Node.prototype._get.call(this, selector);
|
2012-10-07 05:35:46 +08:00
|
|
|
var children = this.getChildren();
|
2012-11-14 16:18:49 +08:00
|
|
|
var len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
2012-10-07 05:35:46 +08:00
|
|
|
retArr = retArr.concat(children[n]._get(selector));
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
return retArr;
|
|
|
|
},
|
|
|
|
// extenders
|
|
|
|
toObject: function() {
|
|
|
|
var obj = Kinetic.Node.prototype.toObject.call(this);
|
2012-10-04 10:38:12 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
obj.children = [];
|
2012-10-04 10:38:12 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
var children = this.getChildren();
|
|
|
|
var len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
|
|
|
var child = children[n];
|
|
|
|
obj.children.push(child.toObject());
|
2012-04-09 12:26:13 +08:00
|
|
|
}
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
return obj;
|
|
|
|
},
|
|
|
|
_getDescendants: function(arr) {
|
|
|
|
var retArr = [];
|
|
|
|
var len = arr.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
|
|
|
var node = arr[n];
|
|
|
|
if(this.isAncestorOf(node)) {
|
|
|
|
retArr.push(node);
|
|
|
|
}
|
2012-04-09 12:26:13 +08:00
|
|
|
}
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
return retArr;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* determine if node is an ancestor
|
|
|
|
* of descendant
|
|
|
|
* @name isAncestorOf
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {Kinetic.Node} node
|
|
|
|
*/
|
|
|
|
isAncestorOf: function(node) {
|
|
|
|
var parent = node.getParent();
|
|
|
|
while(parent) {
|
|
|
|
if(parent._id === this._id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
parent = parent.getParent();
|
|
|
|
}
|
2012-09-26 03:06:02 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
return false;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* clone node
|
|
|
|
* @name clone
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {Object} attrs override attrs
|
|
|
|
*/
|
|
|
|
clone: function(obj) {
|
|
|
|
// call super method
|
|
|
|
var node = Kinetic.Node.prototype.clone.call(this, obj)
|
2012-07-07 12:45:18 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// perform deep clone on containers
|
|
|
|
for(var key in this.children) {
|
|
|
|
node.add(this.children[key].clone());
|
2012-07-07 12:45:18 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
return node;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get shapes that intersect a point
|
|
|
|
* @name getIntersections
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {Object} point
|
|
|
|
*/
|
|
|
|
getIntersections: function() {
|
|
|
|
var pos = Kinetic.Type._getXY(Array.prototype.slice.call(arguments));
|
|
|
|
var arr = [];
|
|
|
|
var shapes = this.get('Shape');
|
2012-07-07 12:45:18 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
var len = shapes.length;
|
2012-11-19 11:50:50 +08:00
|
|
|
for(var n = 0; n < len; n++) {
|
2012-12-02 04:04:10 +08:00
|
|
|
var shape = shapes[n];
|
|
|
|
if(shape.isVisible() && shape.intersects(pos)) {
|
|
|
|
arr.push(shape);
|
|
|
|
}
|
2012-11-19 11:50:50 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
return arr;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set children indices
|
|
|
|
*/
|
|
|
|
_setChildrenIndices: function() {
|
2012-11-19 11:50:50 +08:00
|
|
|
var children = this.children, len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
2012-12-02 04:04:10 +08:00
|
|
|
children[n].index = n;
|
2012-11-19 11:50:50 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/*
|
|
|
|
* draw both scene and hit graphs
|
|
|
|
*/
|
|
|
|
draw: function() {
|
|
|
|
this.drawScene();
|
|
|
|
this.drawHit();
|
|
|
|
},
|
2012-12-11 16:08:59 +08:00
|
|
|
drawScene: function(canvas) {
|
2013-02-16 10:20:34 +08:00
|
|
|
var clip = !!this.getClipFunc() && canvas;
|
|
|
|
|
|
|
|
if (clip) {
|
|
|
|
canvas._clip(this);
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
if(this.isVisible()) {
|
|
|
|
var children = this.children, len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
2012-12-11 16:08:59 +08:00
|
|
|
children[n].drawScene(canvas);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
}
|
2013-02-16 10:20:34 +08:00
|
|
|
if (clip) {
|
|
|
|
canvas.getContext().restore();
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
drawHit: function() {
|
2013-02-16 10:20:34 +08:00
|
|
|
var clip = !!this.getClipFunc() && this.nodeType !== 'Stage',
|
|
|
|
hitCanvas;
|
|
|
|
|
|
|
|
if (clip) {
|
|
|
|
hitCanvas = this.getLayer().hitCanvas;
|
|
|
|
hitCanvas._clip(this);
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
if(this.isVisible() && this.isListening()) {
|
|
|
|
var children = this.children, len = children.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
|
|
|
children[n].drawHit();
|
|
|
|
}
|
|
|
|
}
|
2013-02-16 10:20:34 +08:00
|
|
|
if (clip) {
|
|
|
|
hitCanvas.getContext().restore();
|
|
|
|
}
|
2012-10-08 10:14:14 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
2013-02-16 10:20:34 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Global.extend(Kinetic.Container, Kinetic.Node);
|
2013-02-16 10:20:34 +08:00
|
|
|
|
|
|
|
// add getters setters
|
2013-03-15 23:33:05 +08:00
|
|
|
Kinetic.Node.addGetterSetter(Kinetic.Container, 'clipFunc');
|
2013-02-16 10:20:34 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* set clipping function
|
|
|
|
* @name setClipFunc
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
* @param {Number} deg
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get clipping function
|
|
|
|
* @name getClipFunc
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
})();
|