greatly improved sprite animation performance by hooking into the global animation object

This commit is contained in:
Eric Rowell 2012-07-07 21:39:03 -07:00
parent a8ab9a2533
commit 30fd5c1fa7
6 changed files with 111 additions and 29 deletions

52
dist/kinetic-core.js vendored
View File

@ -363,12 +363,22 @@ Kinetic.Animation = {
},
_runFrames: function() {
var nodes = {};
/*
* 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
*/
for(var n = 0; n < this.animations.length; n++) {
var anim = this.animations[n];
if(anim.node && anim.node._id !== undefined) {
nodes[anim.node._id] = anim.node;
}
anim.func(this.frame);
// if animation object has a function, execute it
if(anim.func) {
anim.func(this.frame);
}
}
for(var key in nodes) {
@ -1012,9 +1022,9 @@ Kinetic.Node = Kinetic.Class.extend({
* clear transition if one is currently running for this
* node
*/
if(this.transAnim !== undefined) {
if(this.transAnim) {
a._removeAnimation(this.transAnim);
this.transAnim = undefined;
this.transAnim = null;
}
/*
@ -1043,7 +1053,7 @@ Kinetic.Node = Kinetic.Class.extend({
trans.onFinished = function() {
// remove animation
a._removeAnimation(anim);
that.transAnim = undefined;
that.transAnim = null;
// callback
if(config.callback !== undefined) {
@ -3677,18 +3687,48 @@ Kinetic.Sprite = Kinetic.Shape.extend({
start: function() {
var that = this;
var layer = this.getLayer();
var ka = Kinetic.Animation;
// if sprite already has an animation, remove it
if(this.anim) {
ka._removeAnimation(this.anim);
this.anim = null;
}
/*
* animation object has no executable function because
* the updates are done with a fixed FPS with the setInterval
* below. The anim object only needs the layer reference for
* redraw
*/
this.anim = {
node: layer
};
/*
* adding the animation with the addAnimation
* method auto generates an id
*/
ka._addAnimation(this.anim);
this.interval = setInterval(function() {
that._updateIndex();
layer.draw();
if(that.afterFrameFunc && that.attrs.index === that.afterFrameIndex) {
that.afterFrameFunc();
}
}, 1000 / this.attrs.frameRate)
}, 1000 / this.attrs.frameRate);
ka._handleAnimation();
},
/**
* stop sprite animation
*/
stop: function() {
var ka = Kinetic.Animation;
if(this.anim) {
ka._removeAnimation(this.anim);
this.anim = null;
}
clearInterval(this.interval);
},
/**

File diff suppressed because one or more lines are too long

View File

@ -26,12 +26,22 @@ Kinetic.Animation = {
},
_runFrames: function() {
var nodes = {};
/*
* 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
*/
for(var n = 0; n < this.animations.length; n++) {
var anim = this.animations[n];
if(anim.node && anim.node._id !== undefined) {
nodes[anim.node._id] = anim.node;
}
anim.func(this.frame);
// if animation object has a function, execute it
if(anim.func) {
anim.func(this.frame);
}
}
for(var key in nodes) {

View File

@ -591,9 +591,9 @@ Kinetic.Node = Kinetic.Class.extend({
* clear transition if one is currently running for this
* node
*/
if(this.transAnim !== undefined) {
if(this.transAnim) {
a._removeAnimation(this.transAnim);
this.transAnim = undefined;
this.transAnim = null;
}
/*
@ -622,7 +622,7 @@ Kinetic.Node = Kinetic.Class.extend({
trans.onFinished = function() {
// remove animation
a._removeAnimation(anim);
that.transAnim = undefined;
that.transAnim = null;
// callback
if(config.callback !== undefined) {

View File

@ -43,18 +43,48 @@ Kinetic.Sprite = Kinetic.Shape.extend({
start: function() {
var that = this;
var layer = this.getLayer();
var ka = Kinetic.Animation;
// if sprite already has an animation, remove it
if(this.anim) {
ka._removeAnimation(this.anim);
this.anim = null;
}
/*
* animation object has no executable function because
* the updates are done with a fixed FPS with the setInterval
* below. The anim object only needs the layer reference for
* redraw
*/
this.anim = {
node: layer
};
/*
* adding the animation with the addAnimation
* method auto generates an id
*/
ka._addAnimation(this.anim);
this.interval = setInterval(function() {
that._updateIndex();
layer.draw();
if(that.afterFrameFunc && that.attrs.index === that.afterFrameIndex) {
that.afterFrameFunc();
}
}, 1000 / this.attrs.frameRate)
}, 1000 / this.attrs.frameRate);
ka._handleAnimation();
},
/**
* stop sprite animation
*/
stop: function() {
var ka = Kinetic.Animation;
if(this.anim) {
ka._removeAnimation(this.anim);
this.anim = null;
}
clearInterval(this.interval);
},
/**

View File

@ -2068,13 +2068,13 @@ Test.prototype.tests = {
animation: 'standing',
animations: anims,
index: 0,
//frameRate: Math.random() * 6 + 6,
frameRate: Math.random() * 6 + 6,
frameRate: 10,
draggable: true,
shadow: {
color: 'black',
blur: 3,
offset: [10, 10],
offset: [3, 1],
alpha: 0.3
}
});
@ -2086,19 +2086,16 @@ Test.prototype.tests = {
stage.add(layer);
// kick once
/*
setTimeout(function() {
sprite.setIndex(0);
sprite.setAnimation('kicking');
setTimeout(function() {
sprite.setAnimation('kicking');
sprite.afterFrame(0, function() {
sprite.setAnimation('standing');
});
}, 2000);
setTimeout(function() {
//sprite.start();
}, 3000);
*/
sprite.afterFrame(0, function() {
sprite.setAnimation('standing');
});
}, 2000);
setTimeout(function() {
sprite.stop();
}, 3000);
};
imageObj.src = '../scorpion-sprite.png';
},
@ -3203,7 +3200,7 @@ Test.prototype.tests = {
// make sure private ids are different
test(rect._id !== clone._id, 'rect and clone ids should be different');
// test user event binding cloning
// test user event binding cloning
test(clicks.length === 0, 'no clicks should have been triggered yet');
rect.simulate('click');
test(clicks.toString() === 'myRect', 'only myRect should have been clicked on');
@ -4535,6 +4532,11 @@ Test.prototype.tests = {
// ANIMATION tests
////////////////////////////////////////////////////////////////////////
/*
* WARNING: make sure that this is the first unit test that uses
* animation because it's accessing the global animation object which could
* be modified by other unit tests
*/
'ANIMATION - test start and stop': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,