2012-03-07 13:45:48 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Container
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
2012-07-09 12:56:52 +08:00
|
|
|
/**
|
|
|
|
* Container constructor. Containers are used to contain nodes or other containers
|
|
|
|
* @constructor
|
|
|
|
* @augments Kinetic.Node
|
|
|
|
* @param {Object} config
|
|
|
|
*/
|
2012-07-04 03:07:27 +08:00
|
|
|
Kinetic.Container = Kinetic.Node.extend({
|
|
|
|
init: function(config) {
|
|
|
|
this.children = [];
|
|
|
|
this._super(config);
|
|
|
|
},
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
|
|
|
* get children
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name getChildren
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
|
|
|
getChildren: function() {
|
|
|
|
return this.children;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* remove all children
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name removeChildren
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
|
|
|
removeChildren: function() {
|
|
|
|
while(this.children.length > 0) {
|
|
|
|
this.remove(this.children[0]);
|
|
|
|
}
|
|
|
|
},
|
2012-05-27 07:49:58 +08:00
|
|
|
/**
|
|
|
|
* add node to container
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name add
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-05-27 07:49:58 +08:00
|
|
|
* @param {Node} child
|
|
|
|
*/
|
|
|
|
add: function(child) {
|
2012-07-04 13:08:59 +08:00
|
|
|
child._id = Kinetic.Global.idCounter++;
|
2012-05-27 07:49:58 +08:00
|
|
|
child.index = this.children.length;
|
|
|
|
child.parent = this;
|
|
|
|
|
|
|
|
this.children.push(child);
|
|
|
|
|
|
|
|
var stage = child.getStage();
|
|
|
|
if(stage === undefined) {
|
2012-07-04 13:08:59 +08:00
|
|
|
var go = Kinetic.Global;
|
2012-05-27 07:49:58 +08:00
|
|
|
go.tempNodes.push(child);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
stage._addId(child);
|
|
|
|
stage._addName(child);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pull in other nodes that are now linked
|
|
|
|
* to a stage
|
|
|
|
*/
|
2012-07-04 13:08:59 +08:00
|
|
|
var go = Kinetic.Global;
|
2012-05-27 07:49:58 +08:00
|
|
|
go._pullNodes(stage);
|
|
|
|
}
|
|
|
|
|
|
|
|
// do extra stuff if needed
|
|
|
|
if(this._add !== undefined) {
|
|
|
|
this._add(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
// chainable
|
|
|
|
return this;
|
|
|
|
},
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
|
|
|
* remove child from container
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name remove
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-03-07 13:45:48 +08:00
|
|
|
* @param {Node} child
|
2012-05-27 07:49:58 +08:00
|
|
|
*/
|
|
|
|
remove: function(child) {
|
2012-06-02 14:56:01 +08:00
|
|
|
if(child && child.index !== undefined && this.children[child.index]._id == child._id) {
|
2012-04-09 08:37:49 +08:00
|
|
|
var stage = this.getStage();
|
2012-04-09 08:50:46 +08:00
|
|
|
if(stage !== undefined) {
|
2012-07-14 12:24:38 +08:00
|
|
|
stage._removeId(child.getId());
|
|
|
|
stage._removeName(child.getName(), child._id);
|
2012-04-09 08:50:46 +08:00
|
|
|
}
|
2012-04-09 08:37:49 +08:00
|
|
|
|
2012-07-04 13:08:59 +08:00
|
|
|
var go = Kinetic.Global;
|
2012-04-09 08:37:49 +08:00
|
|
|
for(var n = 0; n < go.tempNodes.length; n++) {
|
|
|
|
var node = go.tempNodes[n];
|
|
|
|
if(node._id === child._id) {
|
|
|
|
go.tempNodes.splice(n, 1);
|
2012-06-02 14:56:01 +08:00
|
|
|
break;
|
2012-04-09 08:37:49 +08:00
|
|
|
}
|
|
|
|
}
|
2012-04-02 01:29:16 +08:00
|
|
|
|
|
|
|
this.children.splice(child.index, 1);
|
|
|
|
this._setChildrenIndices();
|
2012-05-27 07:49:58 +08:00
|
|
|
|
2012-06-02 14:56:01 +08:00
|
|
|
// remove children
|
2012-07-05 13:04:03 +08:00
|
|
|
while(child.children && child.children.length > 0) {
|
|
|
|
child.remove(child.children[0]);
|
2012-06-02 14:56:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// do extra stuff if needed
|
|
|
|
if(this._remove !== undefined) {
|
|
|
|
this._remove(child);
|
|
|
|
}
|
2012-05-27 07:49:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// chainable
|
|
|
|
return this;
|
2012-03-07 13:45:48 +08:00
|
|
|
},
|
2012-04-09 12:26:13 +08:00
|
|
|
/**
|
2012-04-09 12:37:10 +08:00
|
|
|
* return an array of nodes that match the selector. Use '#' for id selections
|
|
|
|
* and '.' for name selections
|
2012-04-09 12:26:13 +08:00
|
|
|
* ex:
|
|
|
|
* var node = stage.get('#foo'); // selects node with id foo
|
|
|
|
* var nodes = layer.get('.bar'); // selects nodes with name bar inside layer
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name get
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-04-09 12:26:13 +08:00
|
|
|
* @param {String} selector
|
|
|
|
*/
|
|
|
|
get: function(selector) {
|
|
|
|
var stage = this.getStage();
|
|
|
|
var arr;
|
|
|
|
var key = selector.slice(1);
|
|
|
|
if(selector.charAt(0) === '#') {
|
|
|
|
arr = stage.ids[key] !== undefined ? [stage.ids[key]] : [];
|
|
|
|
}
|
|
|
|
else if(selector.charAt(0) === '.') {
|
|
|
|
arr = stage.names[key] !== undefined ? stage.names[key] : [];
|
|
|
|
}
|
2012-04-28 13:54:39 +08:00
|
|
|
else if(selector === 'Shape' || selector === 'Group' || selector === 'Layer') {
|
|
|
|
return this._getNodes(selector);
|
|
|
|
}
|
2012-04-09 12:26:13 +08:00
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var retArr = [];
|
|
|
|
for(var n = 0; n < arr.length; n++) {
|
|
|
|
var node = arr[n];
|
|
|
|
if(this.isAncestorOf(node)) {
|
|
|
|
retArr.push(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retArr;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* determine if node is an ancestor
|
|
|
|
* of descendant
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name isAncestorOf
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-04-09 12:26:13 +08:00
|
|
|
* @param {Kinetic.Node} node
|
|
|
|
*/
|
|
|
|
isAncestorOf: function(node) {
|
|
|
|
if(this.nodeType === 'Stage') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
var parent = node.getParent();
|
|
|
|
while(parent) {
|
|
|
|
if(parent._id === this._id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
parent = parent.getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
2012-07-07 12:45:18 +08:00
|
|
|
/**
|
|
|
|
* get shapes that intersect a point
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name getIntersections
|
|
|
|
* @methodOf Kinetic.Container.prototype
|
2012-07-07 12:45:18 +08:00
|
|
|
* @param {Object} point
|
|
|
|
*/
|
|
|
|
getIntersections: function() {
|
|
|
|
var pos = Kinetic.Type._getXY(Array.prototype.slice.call(arguments));
|
|
|
|
var arr = [];
|
|
|
|
var shapes = this.get('Shape');
|
|
|
|
|
|
|
|
for(var n = 0; n < shapes.length; n++) {
|
|
|
|
var shape = shapes[n];
|
|
|
|
if(shape.isVisible() && shape.intersects(pos)) {
|
|
|
|
arr.push(shape);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
},
|
2012-04-28 13:54:39 +08:00
|
|
|
/**
|
|
|
|
* get all shapes inside container
|
|
|
|
*/
|
|
|
|
_getNodes: function(sel) {
|
|
|
|
var arr = [];
|
|
|
|
function traverse(cont) {
|
|
|
|
var children = cont.getChildren();
|
|
|
|
for(var n = 0; n < children.length; n++) {
|
|
|
|
var child = children[n];
|
|
|
|
if(child.nodeType === sel) {
|
|
|
|
arr.push(child);
|
|
|
|
}
|
|
|
|
else if(child.nodeType !== 'Shape') {
|
|
|
|
traverse(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
traverse(this);
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
},
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
|
|
|
* draw children
|
|
|
|
*/
|
2012-07-15 07:25:56 +08:00
|
|
|
_drawChildren: function(layer) {
|
2012-04-15 03:04:45 +08:00
|
|
|
var stage = this.getStage();
|
2012-03-07 13:45:48 +08:00
|
|
|
var children = this.children;
|
|
|
|
for(var n = 0; n < children.length; n++) {
|
|
|
|
var child = children[n];
|
2012-05-27 15:07:36 +08:00
|
|
|
if(child.nodeType === 'Shape') {
|
|
|
|
if(child.isVisible() && stage.isVisible()) {
|
toDataURL() is now synchronous, and works with all nodes, including the stage, layers, groups, and shapes. This also sets things up nicely for node caching. You can now cache anything, including the whole stage, layers, groups, or shapes, manifested as Kinetic Images that were instantiated with data urls
2012-07-15 09:10:37 +08:00
|
|
|
child._draw( layer ? layer : child.getLayer());
|
2012-05-27 15:07:36 +08:00
|
|
|
}
|
2012-03-18 01:28:25 +08:00
|
|
|
}
|
|
|
|
else {
|
2012-07-15 07:25:56 +08:00
|
|
|
child.draw(layer);
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set children indices
|
|
|
|
*/
|
|
|
|
_setChildrenIndices: function() {
|
|
|
|
/*
|
|
|
|
* if reordering Layers, remove all canvas elements
|
|
|
|
* from the container except the buffer and backstage canvases
|
|
|
|
* and then readd all the layers
|
|
|
|
*/
|
2012-04-05 13:57:36 +08:00
|
|
|
if(this.nodeType === 'Stage') {
|
2012-03-18 01:28:25 +08:00
|
|
|
var canvases = this.content.children;
|
2012-03-07 13:45:48 +08:00
|
|
|
var bufferCanvas = canvases[0];
|
|
|
|
var backstageCanvas = canvases[1];
|
|
|
|
|
2012-03-18 01:28:25 +08:00
|
|
|
this.content.innerHTML = '';
|
|
|
|
this.content.appendChild(bufferCanvas);
|
|
|
|
this.content.appendChild(backstageCanvas);
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for(var n = 0; n < this.children.length; n++) {
|
|
|
|
this.children[n].index = n;
|
|
|
|
|
2012-04-05 13:57:36 +08:00
|
|
|
if(this.nodeType === 'Stage') {
|
2012-03-18 01:28:25 +08:00
|
|
|
this.content.appendChild(this.children[n].canvas);
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-04 03:07:27 +08:00
|
|
|
});
|