Merge pull request #1068 from nnnick/animation-refactory

Animation refactory
This commit is contained in:
William Entriken
2015-05-04 15:55:59 -04:00

View File

@@ -915,7 +915,7 @@
},
stop : function(){
// Stops any current animation loop occuring
cancelAnimFrame(this.animationFrame);
Chart.animationService.cancelAnimation(this);
return this;
},
resize : function(callback){
@@ -939,15 +939,26 @@
if (reflow){
this.reflow();
}
if (this.options.animation && !reflow){
helpers.animationLoop(
this.draw,
this.options.animationSteps,
this.options.animationEasing,
this.options.onAnimationProgress,
this.options.onAnimationComplete,
this
);
var animation = new Chart.Animation();
animation.numSteps = this.options.animationSteps;
animation.easing = this.options.animationEasing;
// render function
animation.render = function(chartInstance, animationObject) {
var easingFunction = helpers.easingEffects[animationObject.easing];
var stepDecimal = animationObject.currentStep / animationObject.numSteps;
var easeDecimal = easingFunction(stepDecimal);
chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
};
// user events
animation.onAnimationProgress = this.options.onAnimationProgress;
animation.onAnimationComplete = this.options.onAnimationComplete;
Chart.animationService.addAnimation(this, animation);
}
else{
this.draw();
@@ -1354,6 +1365,16 @@
}
});
Chart.Animation = Chart.Element.extend({
currentStep: null, // the current animation step
numSteps: 60, // default number of steps
easing: "", // the easing to use for this animation
render: null, // render function used by the animation service
onAnimationProgress: null, // user specified callback to fire on each step of the animation
onAnimationComplete: null, // user specified callback to fire when the animation finishes
});
Chart.Tooltip = Chart.Element.extend({
draw : function(){
@@ -2059,6 +2080,90 @@
}
});
Chart.animationService = {
frameDuration: 17,
animations: [],
dropFrames: 0,
addAnimation: function(chartInstance, animationObject) {
for (var index = 0; index < this.animations.length; ++ index){
if (this.animations[index].chartInstance === chartInstance){
// replacing an in progress animation
this.animations[index].animationObject = animationObject;
return;
}
}
this.animations.push({
chartInstance: chartInstance,
animationObject: animationObject
});
// If there are no animations queued, manually kickstart a digest, for lack of a better word
if (this.animations.length == 1) {
helpers.requestAnimFrame.call(window, this.digestWrapper);
}
},
// Cancel the animation for a given chart instance
cancelAnimation: function(chartInstance) {
var index = helpers.findNextWhere(this.animations, function(animationWrapper) {
return animationWrapper.chartInstance === chartInstance;
});
if (index)
{
this.animations.splice(index, 1);
}
},
// calls startDigest with the proper context
digestWrapper: function() {
Chart.animationService.startDigest.call(Chart.animationService);
},
startDigest: function() {
var startTime = Date.now();
var framesToDrop = 0;
if(this.dropFrames > 1){
framesToDrop = Math.floor(this.dropFrames);
this.dropFrames -= framesToDrop;
}
for (var i = 0; i < this.animations.length; i++) {
if (this.animations[i].animationObject.currentStep === null){
this.animations[i].animationObject.currentStep = 0;
}
this.animations[i].animationObject.currentStep += 1 + framesToDrop;
if(this.animations[i].animationObject.currentStep > this.animations[i].animationObject.numSteps){
this.animations[i].animationObject.currentStep = this.animations[i].animationObject.numSteps;
}
this.animations[i].animationObject.render(this.animations[i].chartInstance, this.animations[i].animationObject);
if (this.animations[i].animationObject.currentStep == this.animations[i].animationObject.numSteps){
// executed the last frame. Remove the animation.
this.animations.splice(i, 1);
// Keep the index in place to offset the splice
i--;
}
}
var endTime = Date.now();
var delay = endTime - startTime - this.frameDuration;
var frameDelay = delay / this.frameDuration;
if(frameDelay > 1){
this.dropFrames += frameDelay;
}
// Do we have more stuff to animate?
if (this.animations.length > 0){
helpers.requestAnimFrame.call(window, this.digestWrapper);
}
}
};
// Attach global event to resize each chart instance when the browser resizes
helpers.addEvent(window, "resize", (function(){
// Basic debounce of resize function so it doesn't hurt performance when resizing browser.