greatly improved animation, transition, and drag and drop performance by dynamically switching between fixed and dynamic frame rates, and also created a single source of truth for the animation frame object

This commit is contained in:
Eric Rowell
2012-11-03 11:16:33 -07:00
parent 1ad12bbbf1
commit 78668b0d38
7 changed files with 61 additions and 54 deletions

View File

@@ -1 +1 @@
Kinetic.Animation=function(a){a||(a={});for(var b in a)this[b]=a[b];this.frame={time:0,timeDiff:0,lastTime:(new Date).getTime()},this.id=Kinetic.Animation.animIdCounter++},Kinetic.Animation.prototype={start:function(){this.stop(),this.frame.lastTime=(new Date).getTime(),Kinetic.Animation._addAnimation(this),Kinetic.Animation._handleAnimation()},stop:function(){Kinetic.Animation._removeAnimation(this)}},Kinetic.Animation.animations=[],Kinetic.Animation.animIdCounter=0,Kinetic.Animation.animRunning=!1,Kinetic.Animation._addAnimation=function(a){this.animations.push(a)},Kinetic.Animation._removeAnimation=function(a){var b=a.id,c=this.animations;for(var d=0;d<c.length;d++)if(c[d].id===b)return this.animations.splice(d,1),!1},Kinetic.Animation._updateFrameObject=function(a){var b=(new Date).getTime();a.frame.timeDiff=b-a.frame.lastTime,a.frame.lastTime=b,a.frame.time+=a.frame.timeDiff},Kinetic.Animation._runFrames=function(){var a={};for(var b=0;b<this.animations.length;b++){var c=this.animations[b];this._updateFrameObject(c),c.node&&c.node._id!==undefined&&(a[c.node._id]=c.node),c.func&&c.func(c.frame)}for(var d in a)a[d].draw()},Kinetic.Animation._animationLoop=function(){if(this.animations.length>0){this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}else this.animRunning=!1},Kinetic.Animation._handleAnimation=function(){var a=this;this.animRunning||(this.animRunning=!0,a._animationLoop())},requestAnimFrame=function(a){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}();
Kinetic.Animation=function(a){a||(a={});for(var b in a)this[b]=a[b];this.id=Kinetic.Animation.animIdCounter++},Kinetic.Animation.prototype={start:function(){this.stop(),Kinetic.Animation._addAnimation(this),Kinetic.Animation._handleAnimation()},stop:function(){Kinetic.Animation._removeAnimation(this)}},Kinetic.Animation.animations=[],Kinetic.Animation.animIdCounter=0,Kinetic.Animation.animRunning=!1,Kinetic.Animation.frame={time:0,timeDiff:0,lastTime:(new Date).getTime(),frameRate:0},Kinetic.Animation.fixedRequestAnimFrame=function(a){window.setTimeout(a,1e3/60)},Kinetic.Animation._addAnimation=function(a){this.animations.push(a)},Kinetic.Animation._removeAnimation=function(a){var b=a.id,c=this.animations;for(var d=0;d<c.length;d++)if(c[d].id===b)return this.animations.splice(d,1),!1},Kinetic.Animation._updateFrameObject=function(){var a=(new Date).getTime();this.frame.timeDiff=a-this.frame.lastTime,this.frame.lastTime=a,this.frame.time+=this.frame.timeDiff,this.frame.frameRate=1e3/this.frame.timeDiff},Kinetic.Animation._runFrames=function(){this._updateFrameObject();var a={};for(var b=0;b<this.animations.length;b++){var c=this.animations[b];c.node&&c.node._id!==undefined&&(a[c.node._id]=c.node),c.func&&c.func(this.frame)}for(var d in a)a[d].draw()},Kinetic.Animation._animationLoop=function(){if(this.animations.length>0){this._runFrames();var a=this;Kinetic.Animation.requestAnimFrame(function(){a._animationLoop()})}else this.animRunning=!1},Kinetic.Animation._handleAnimation=function(){var a=this;this.animRunning||(this.animRunning=!0,a._animationLoop())},Kinetic.Animation.requestAnimFrame=function(a){var b=Kinetic.DD&&Kinetic.DD.moving?this.fixedRequestAnimFrame:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||Kinetic.Animation.fixedRequestAnimFrame;b(a)};

View File

@@ -3,7 +3,7 @@
* http://www.kineticjs.com/
* Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses.
* Date: Oct 28 2012
* Date: Nov 03 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
* http://www.kineticjs.com/
* Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses.
* Date: Oct 28 2012
* Date: Nov 03 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*
@@ -980,13 +980,6 @@ Kinetic.Animation = function(config) {
this[key] = config[key];
}
// add frame object
this.frame = {
time: 0,
timeDiff: 0,
lastTime: new Date().getTime()
};
this.id = Kinetic.Animation.animIdCounter++;
};
/*
@@ -1000,7 +993,6 @@ Kinetic.Animation.prototype = {
*/
start: function() {
this.stop();
this.frame.lastTime = new Date().getTime();
Kinetic.Animation._addAnimation(this);
Kinetic.Animation._handleAnimation();
},
@@ -1016,6 +1008,17 @@ Kinetic.Animation.prototype = {
Kinetic.Animation.animations = [];
Kinetic.Animation.animIdCounter = 0;
Kinetic.Animation.animRunning = false;
Kinetic.Animation.frame = {
time: 0,
timeDiff: 0,
lastTime: new Date().getTime(),
frameRate: 0
};
Kinetic.Animation.fixedRequestAnimFrame = function(callback) {
window.setTimeout(callback, 1000 / 60);
};
Kinetic.Animation._addAnimation = function(anim) {
this.animations.push(anim);
};
@@ -1029,13 +1032,15 @@ Kinetic.Animation._removeAnimation = function(anim) {
}
}
};
Kinetic.Animation._updateFrameObject = function(anim) {
Kinetic.Animation._updateFrameObject = function() {
var time = new Date().getTime();
anim.frame.timeDiff = time - anim.frame.lastTime;
anim.frame.lastTime = time;
anim.frame.time += anim.frame.timeDiff;
this.frame.timeDiff = time - this.frame.lastTime;
this.frame.lastTime = time;
this.frame.time += this.frame.timeDiff;
this.frame.frameRate = 1000 / this.frame.timeDiff;
};
Kinetic.Animation._runFrames = function() {
this._updateFrameObject();
var nodes = {};
/*
* loop through all animations and execute animation
@@ -1046,13 +1051,12 @@ Kinetic.Animation._runFrames = function() {
*/
for(var n = 0; n < this.animations.length; n++) {
var anim = this.animations[n];
this._updateFrameObject(anim);
if(anim.node && anim.node._id !== undefined) {
nodes[anim.node._id] = anim.node;
}
// if animation object has a function, execute it
if(anim.func) {
anim.func(anim.frame);
anim.func(this.frame);
}
}
@@ -1064,7 +1068,7 @@ Kinetic.Animation._animationLoop = function() {
if(this.animations.length > 0) {
this._runFrames();
var that = this;
requestAnimFrame(function() {
Kinetic.Animation.requestAnimFrame(function() {
that._animationLoop();
});
}
@@ -1079,12 +1083,11 @@ Kinetic.Animation._handleAnimation = function() {
that._animationLoop();
}
};
requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Kinetic.Animation.requestAnimFrame = function(callback) {
var raf = Kinetic.DD && Kinetic.DD.moving ? this.fixedRequestAnimFrame : window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || Kinetic.Animation.fixedRequestAnimFrame;
raf(callback);
};
/**
* Node constructor.&nbsp; Nodes are entities that can be transformed, layered,
@@ -1681,9 +1684,10 @@ Kinetic.Node.prototype = {
* @name simulate
* @methodOf Kinetic.Node.prototype
* @param {String} eventType
* @param {Object} event attribute
*/
simulate: function(eventType) {
this._handleEvent(eventType, {});
simulate: function(eventType, evt) {
this._handleEvent(eventType, evt || {});
},
/**
* get absolute transform of the node which takes into

File diff suppressed because one or more lines are too long

View File

@@ -14,13 +14,6 @@ Kinetic.Animation = function(config) {
this[key] = config[key];
}
// add frame object
this.frame = {
time: 0,
timeDiff: 0,
lastTime: new Date().getTime()
};
this.id = Kinetic.Animation.animIdCounter++;
};
/*
@@ -34,7 +27,6 @@ Kinetic.Animation.prototype = {
*/
start: function() {
this.stop();
this.frame.lastTime = new Date().getTime();
Kinetic.Animation._addAnimation(this);
Kinetic.Animation._handleAnimation();
},
@@ -50,6 +42,17 @@ Kinetic.Animation.prototype = {
Kinetic.Animation.animations = [];
Kinetic.Animation.animIdCounter = 0;
Kinetic.Animation.animRunning = false;
Kinetic.Animation.frame = {
time: 0,
timeDiff: 0,
lastTime: new Date().getTime(),
frameRate: 0
};
Kinetic.Animation.fixedRequestAnimFrame = function(callback) {
window.setTimeout(callback, 1000 / 60);
};
Kinetic.Animation._addAnimation = function(anim) {
this.animations.push(anim);
};
@@ -63,13 +66,15 @@ Kinetic.Animation._removeAnimation = function(anim) {
}
}
};
Kinetic.Animation._updateFrameObject = function(anim) {
Kinetic.Animation._updateFrameObject = function() {
var time = new Date().getTime();
anim.frame.timeDiff = time - anim.frame.lastTime;
anim.frame.lastTime = time;
anim.frame.time += anim.frame.timeDiff;
this.frame.timeDiff = time - this.frame.lastTime;
this.frame.lastTime = time;
this.frame.time += this.frame.timeDiff;
this.frame.frameRate = 1000 / this.frame.timeDiff;
};
Kinetic.Animation._runFrames = function() {
this._updateFrameObject();
var nodes = {};
/*
* loop through all animations and execute animation
@@ -80,13 +85,12 @@ Kinetic.Animation._runFrames = function() {
*/
for(var n = 0; n < this.animations.length; n++) {
var anim = this.animations[n];
this._updateFrameObject(anim);
if(anim.node && anim.node._id !== undefined) {
nodes[anim.node._id] = anim.node;
}
// if animation object has a function, execute it
if(anim.func) {
anim.func(anim.frame);
anim.func(this.frame);
}
}
@@ -98,7 +102,7 @@ Kinetic.Animation._animationLoop = function() {
if(this.animations.length > 0) {
this._runFrames();
var that = this;
requestAnimFrame(function() {
Kinetic.Animation.requestAnimFrame(function() {
that._animationLoop();
});
}
@@ -113,9 +117,8 @@ Kinetic.Animation._handleAnimation = function() {
that._animationLoop();
}
};
requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Kinetic.Animation.requestAnimFrame = function(callback) {
var raf = Kinetic.DD && Kinetic.DD.moving ? this.fixedRequestAnimFrame : window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || Kinetic.Animation.fixedRequestAnimFrame;
raf(callback);
};

View File

@@ -109,7 +109,7 @@ Test.prototype.tests = {
easing: 'bounce-ease-out'
});
},
'*TRANSITION - all transition types': function(containerId) {
'TRANSITION - all transition types': function(containerId) {
document.getElementById(containerId).style.height = '300px';
var stage = new Kinetic.Stage({
@@ -713,7 +713,7 @@ Test.prototype.tests = {
layer.add(redCircle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop elastic star with shadow': function(containerId) {
'*DRAG AND DROP - drag and drop elastic star with shadow': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,