2012-12-02 04:04:10 +08:00
|
|
|
(function() {
|
2012-08-04 15:23:56 +08:00
|
|
|
/**
|
2013-05-06 11:57:31 +08:00
|
|
|
* Animation constructor. A stage is used to contain multiple layers and handle
|
2012-12-02 04:04:10 +08:00
|
|
|
* @constructor
|
2013-05-16 00:27:22 +08:00
|
|
|
* @memberof Kinetic
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {Function} func function executed on each animation frame
|
2013-05-06 11:57:31 +08:00
|
|
|
* @param {Kinetic.Layer|Array} [layers] layer(s) to be redrawn. Can be a layer, an array of layers, or null. Not specifying a node will result in no redraw.
|
2012-08-04 15:23:56 +08:00
|
|
|
*/
|
2013-05-06 11:57:31 +08:00
|
|
|
Kinetic.Animation = function(func, layers) {
|
2012-12-02 04:04:10 +08:00
|
|
|
this.func = func;
|
2013-05-06 11:57:31 +08:00
|
|
|
this.setLayers(layers);
|
2012-12-02 04:04:10 +08:00
|
|
|
this.id = Kinetic.Animation.animIdCounter++;
|
2012-12-12 14:34:58 +08:00
|
|
|
this.frame = {
|
|
|
|
time: 0,
|
|
|
|
timeDiff: 0,
|
|
|
|
lastTime: new Date().getTime()
|
|
|
|
};
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
|
|
|
/*
|
|
|
|
* Animation methods
|
2012-08-04 15:23:56 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Animation.prototype = {
|
2013-05-06 11:57:31 +08:00
|
|
|
/**
|
|
|
|
* set layers to be redrawn on each animation frame
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2013-05-06 11:57:31 +08:00
|
|
|
* @param {Kinetic.Layer|Array} [layers] layer(s) to be redrawn. Can be a layer, an array of layers, or null. Not specifying a node will result in no redraw.
|
|
|
|
*/
|
|
|
|
setLayers: function(layers) {
|
|
|
|
var lays = [];
|
|
|
|
// if passing in no layers
|
|
|
|
if (!layers) {
|
2013-05-12 11:07:20 +08:00
|
|
|
lays = [];
|
2013-05-06 11:57:31 +08:00
|
|
|
}
|
|
|
|
// if passing in an array of Layers
|
2013-05-08 14:51:02 +08:00
|
|
|
else if (Kinetic.Util._isArray(layers)) {
|
2013-05-06 11:57:31 +08:00
|
|
|
lays = layers;
|
|
|
|
}
|
|
|
|
// if passing in a Layer
|
|
|
|
else {
|
|
|
|
lays = [layers];
|
|
|
|
}
|
|
|
|
|
|
|
|
this.layers = lays;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get layers
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2013-05-06 11:57:31 +08:00
|
|
|
*/
|
|
|
|
getLayers: function() {
|
|
|
|
return this.layers;
|
|
|
|
},
|
2013-05-06 13:09:32 +08:00
|
|
|
/**
|
|
|
|
* add layer. Returns true if the layer was added, and false if it was not
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2013-05-06 13:09:32 +08:00
|
|
|
* @param {Kinetic.Layer} layer
|
|
|
|
*/
|
|
|
|
addLayer: function(layer) {
|
|
|
|
var layers = this.layers,
|
|
|
|
len, n;
|
|
|
|
|
|
|
|
if (layers) {
|
|
|
|
len = layers.length;
|
|
|
|
|
|
|
|
// don't add the layer if it already exists
|
|
|
|
for (n = 0; n < len; n++) {
|
|
|
|
if (layers[n]._id === layer._id) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.layers = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
this.layers.push(layer);
|
|
|
|
return true;
|
|
|
|
},
|
2013-01-14 11:59:35 +08:00
|
|
|
/**
|
2013-01-14 14:52:31 +08:00
|
|
|
* determine if animation is running or not. returns true or false
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2013-01-14 11:59:35 +08:00
|
|
|
*/
|
|
|
|
isRunning: function() {
|
|
|
|
var a = Kinetic.Animation, animations = a.animations;
|
|
|
|
for(var n = 0; n < animations.length; n++) {
|
|
|
|
if(animations[n].id === this.id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* start animation
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
|
|
|
start: function() {
|
|
|
|
this.stop();
|
2012-12-12 14:34:58 +08:00
|
|
|
this.frame.timeDiff = 0;
|
|
|
|
this.frame.lastTime = new Date().getTime();
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Animation._addAnimation(this);
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* stop animation
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Animation.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
|
|
|
stop: function() {
|
|
|
|
Kinetic.Animation._removeAnimation(this);
|
2012-12-12 14:34:58 +08:00
|
|
|
},
|
2013-01-08 11:36:12 +08:00
|
|
|
_updateFrameObject: function(time) {
|
2012-12-12 14:34:58 +08:00
|
|
|
this.frame.timeDiff = time - this.frame.lastTime;
|
|
|
|
this.frame.lastTime = time;
|
|
|
|
this.frame.time += this.frame.timeDiff;
|
|
|
|
this.frame.frameRate = 1000 / this.frame.timeDiff;
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Kinetic.Animation.animations = [];
|
|
|
|
Kinetic.Animation.animIdCounter = 0;
|
|
|
|
Kinetic.Animation.animRunning = false;
|
2012-11-04 02:16:33 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Animation._addAnimation = function(anim) {
|
|
|
|
this.animations.push(anim);
|
2012-12-31 15:14:23 +08:00
|
|
|
this._handleAnimation();
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
|
|
|
Kinetic.Animation._removeAnimation = function(anim) {
|
2013-05-12 07:43:09 +08:00
|
|
|
var id = anim.id, animations = this.animations, len = animations.length;
|
|
|
|
for(var n = 0; n < len; n++) {
|
2012-12-02 04:04:10 +08:00
|
|
|
if(animations[n].id === id) {
|
|
|
|
this.animations.splice(n, 1);
|
|
|
|
break;
|
|
|
|
}
|
2012-07-04 14:00:52 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
2012-12-12 14:34:58 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Animation._runFrames = function() {
|
2013-05-06 11:57:31 +08:00
|
|
|
var layerHash = {},
|
|
|
|
animations = this.animations,
|
|
|
|
anim, layers, func, n, i, layersLen, layer, key;
|
2012-12-02 04:04:10 +08:00
|
|
|
/*
|
|
|
|
* loop through all animations and execute animation
|
|
|
|
* function. if the animation object has specified node,
|
|
|
|
* we can add the node to the nodes hash to eliminate
|
|
|
|
* drawing the same node multiple times. The node property
|
|
|
|
* can be the stage itself or a layer
|
|
|
|
*/
|
2013-01-10 00:27:57 +08:00
|
|
|
/*
|
|
|
|
* WARNING: don't cache animations.length because it could change while
|
|
|
|
* the for loop is running, causing a JS error
|
|
|
|
*/
|
2013-05-11 13:10:05 +08:00
|
|
|
for(n = 0; n < animations.length; n++) {
|
2013-05-06 11:57:31 +08:00
|
|
|
anim = animations[n];
|
|
|
|
layers = anim.layers;
|
|
|
|
func = anim.func;
|
|
|
|
|
2013-01-08 11:36:12 +08:00
|
|
|
anim._updateFrameObject(new Date().getTime());
|
2013-05-12 11:07:20 +08:00
|
|
|
layersLen = layers.length;
|
2013-05-06 11:57:31 +08:00
|
|
|
|
2013-05-12 11:07:20 +08:00
|
|
|
for (i=0; i<layersLen; i++) {
|
|
|
|
layer = layers[i]
|
|
|
|
if(layer._id !== undefined) {
|
|
|
|
layerHash[layer._id] = layer;
|
2013-05-06 11:57:31 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2013-05-12 11:07:20 +08:00
|
|
|
|
|
|
|
// if animation object has a function, execute it
|
|
|
|
if(func) {
|
|
|
|
func.call(anim, anim.frame);
|
|
|
|
}
|
2012-07-04 14:00:52 +08:00
|
|
|
}
|
2012-08-01 14:23:00 +08:00
|
|
|
|
2013-05-06 11:57:31 +08:00
|
|
|
for(key in layerHash) {
|
|
|
|
layerHash[key].draw();
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Kinetic.Animation._animationLoop = function() {
|
2013-01-08 11:36:12 +08:00
|
|
|
var that = this;
|
2012-12-02 04:04:10 +08:00
|
|
|
if(this.animations.length > 0) {
|
|
|
|
this._runFrames();
|
|
|
|
Kinetic.Animation.requestAnimFrame(function() {
|
|
|
|
that._animationLoop();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.animRunning = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Kinetic.Animation._handleAnimation = function() {
|
2012-07-04 14:00:52 +08:00
|
|
|
var that = this;
|
2012-12-02 04:04:10 +08:00
|
|
|
if(!this.animRunning) {
|
|
|
|
this.animRunning = true;
|
2012-07-04 14:00:52 +08:00
|
|
|
that._animationLoop();
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
};
|
2013-01-08 11:36:12 +08:00
|
|
|
RAF = (function() {
|
2013-04-29 05:14:45 +08:00
|
|
|
return window.requestAnimationFrame
|
|
|
|
|| window.webkitRequestAnimationFrame
|
|
|
|
|| window.mozRequestAnimationFrame
|
|
|
|
|| window.oRequestAnimationFrame
|
|
|
|
|| window.msRequestAnimationFrame
|
2013-05-10 00:45:30 +08:00
|
|
|
|| FRAF;
|
2013-01-08 11:36:12 +08:00
|
|
|
})();
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-04-29 05:14:45 +08:00
|
|
|
function FRAF(callback) {
|
|
|
|
window.setTimeout(callback, 1000 / 60);
|
|
|
|
}
|
|
|
|
|
2013-01-08 11:36:12 +08:00
|
|
|
Kinetic.Animation.requestAnimFrame = function(callback) {
|
2013-04-29 05:14:45 +08:00
|
|
|
var raf = Kinetic.DD && Kinetic.DD.isDragging ? FRAF : RAF;
|
2013-01-14 13:52:31 +08:00
|
|
|
raf(callback);
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
2013-01-28 13:29:22 +08:00
|
|
|
|
|
|
|
var moveTo = Kinetic.Node.prototype.moveTo;
|
|
|
|
Kinetic.Node.prototype.moveTo = function(container) {
|
2013-05-12 07:43:09 +08:00
|
|
|
moveTo.call(this, container);
|
2013-01-28 13:29:22 +08:00
|
|
|
};
|
|
|
|
|
2013-05-08 14:17:57 +08:00
|
|
|
Kinetic.Layer.batchAnim = new Kinetic.Animation(function() {
|
|
|
|
if (this.getLayers().length === 0) {
|
|
|
|
this.stop();
|
|
|
|
}
|
|
|
|
this.setLayers([]);
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get batch draw
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Kinetic.Layer.prototype
|
2013-05-08 14:17:57 +08:00
|
|
|
*/
|
|
|
|
Kinetic.Layer.prototype.batchDraw = function() {
|
|
|
|
var batchAnim = Kinetic.Layer.batchAnim;
|
|
|
|
batchAnim.addLayer(this);
|
|
|
|
|
|
|
|
if (!batchAnim.isRunning()) {
|
|
|
|
batchAnim.start();
|
|
|
|
}
|
|
|
|
};
|
2013-05-12 07:43:09 +08:00
|
|
|
})();
|