fixed animation race condition bug that sometimes produced multiple requestAnimFrame calls, and also changed throttle property to be in fps (it used to be in ms). This will make it more consistent with other properties related to frame rates

This commit is contained in:
Eric Rowell 2012-05-03 12:05:54 -07:00
parent 3585e000b6
commit 7d92a2099e
6 changed files with 44 additions and 34 deletions

29
dist/kinetic-core.js vendored
View File

@ -3,7 +3,7 @@
* http://www.kineticjs.com/
* Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses.
* Date: May 02 2012
* Date: May 03 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*
@ -44,6 +44,7 @@ Kinetic.GlobalObject = {
tempNodes: [],
animations: [],
animIdCounter: 0,
animRunning: false,
dragTimeInterval: 0,
maxDragTimeInterval: 20,
frame: {
@ -132,12 +133,14 @@ Kinetic.GlobalObject = {
});
}
else {
this.animRunning = false;
this.frame.lastTime = 0;
}
},
_handleAnimation: function() {
var that = this;
if(this.animations.length > 0) {
if(!this.animRunning) {
this.animRunning = true;
that._animationLoop();
}
else {
@ -2177,7 +2180,7 @@ Kinetic.GlobalObject.extend(Kinetic.Stage, Kinetic.Node);
*/
Kinetic.Layer = function(config) {
this.setDefaultAttrs({
throttle: 12
throttle: 80
});
this.nodeType = 'Layer';
@ -2206,10 +2209,11 @@ Kinetic.Layer.prototype = {
var date = new Date();
var time = date.getTime();
var timeDiff = time - this.lastDrawTime;
var tt = 1000 / throttle;
if(timeDiff >= throttle) {
if(timeDiff >= tt) {
this._draw();
this.lastDrawTime = time;
if(this.drawTimeout !== undefined) {
clearTimeout(this.drawTimeout);
this.drawTimeout = undefined;
@ -2221,15 +2225,12 @@ Kinetic.Layer.prototype = {
*/
else if(this.drawTimeout === undefined) {
var that = this;
/*
* if timeout duration is too short, we will
* get a lot of unecessary layer draws. Make sure
* that the timeout is slightly more than the throttle
* amount
*/
/*
* wait 17ms before trying again (60fps)
*/
this.drawTimeout = setTimeout(function() {
that.draw();
}, throttle + 10);
}, 17);
}
},
/**
@ -2299,6 +2300,10 @@ Kinetic.Layer.prototype = {
* private draw children
*/
_draw: function() {
var date = new Date();
var time = date.getTime();
this.lastDrawTime = time;
// before draw handler
if(this.beforeDrawFunc !== undefined) {
this.beforeDrawFunc();

File diff suppressed because one or more lines are too long

View File

@ -16,6 +16,7 @@ Kinetic.GlobalObject = {
tempNodes: [],
animations: [],
animIdCounter: 0,
animRunning: false,
dragTimeInterval: 0,
maxDragTimeInterval: 20,
frame: {
@ -104,12 +105,14 @@ Kinetic.GlobalObject = {
});
}
else {
this.animRunning = false;
this.frame.lastTime = 0;
}
},
_handleAnimation: function() {
var that = this;
if(this.animations.length > 0) {
if(!this.animRunning) {
this.animRunning = true;
that._animationLoop();
}
else {

View File

@ -11,7 +11,7 @@
*/
Kinetic.Layer = function(config) {
this.setDefaultAttrs({
throttle: 12
throttle: 80
});
this.nodeType = 'Layer';
@ -40,10 +40,11 @@ Kinetic.Layer.prototype = {
var date = new Date();
var time = date.getTime();
var timeDiff = time - this.lastDrawTime;
var tt = 1000 / throttle;
if(timeDiff >= throttle) {
if(timeDiff >= tt) {
this._draw();
this.lastDrawTime = time;
if(this.drawTimeout !== undefined) {
clearTimeout(this.drawTimeout);
this.drawTimeout = undefined;
@ -55,15 +56,12 @@ Kinetic.Layer.prototype = {
*/
else if(this.drawTimeout === undefined) {
var that = this;
/*
* if timeout duration is too short, we will
* get a lot of unecessary layer draws. Make sure
* that the timeout is slightly more than the throttle
* amount
*/
/*
* wait 17ms before trying again (60fps)
*/
this.drawTimeout = setTimeout(function() {
that.draw();
}, throttle + 10);
}, 17);
}
},
/**
@ -133,6 +131,10 @@ Kinetic.Layer.prototype = {
* private draw children
*/
_draw: function() {
var date = new Date();
var time = date.getTime();
this.lastDrawTime = time;
// before draw handler
if(this.beforeDrawFunc !== undefined) {
this.beforeDrawFunc();

View File

@ -10,7 +10,7 @@ function log(message) {
* Test constructor
*/
function Test() {
this.testOnly = 'SHAPES - add sprite';
this.testOnly = '';
this.counter = 0;
}
/**

View File

@ -88,7 +88,7 @@ Test.prototype.tests = {
group.add(circle);
layer.draw();
var expectedJson = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":12,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true},"nodeType":"Shape","shapeType":"Circle"}]}]}]}';
var expectedJson = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true},"nodeType":"Shape","shapeType":"Circle"}]}]}]}';
test(stage.toJSON() === expectedJson, 'problem with serialization');
},
'STAGE - reset stage': function(containerId) {
@ -173,7 +173,7 @@ Test.prototype.tests = {
height: 200
});
var json = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":12,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true},"nodeType":"Shape","shapeType":"Circle"}]}]}]}';
var json = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true},"nodeType":"Shape","shapeType":"Circle"}]}]}]}';
stage.load(json);
test(stage.toJSON() === json, "serialized stage is incorrect");
@ -209,7 +209,7 @@ Test.prototype.tests = {
group.add(triangle);
layer.draw();
var expectedJson = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":12,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"fill":"#00D2FF","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
var expectedJson = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"fill":"#00D2FF","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
test(stage.toJSON() === expectedJson, "problem with serialization");
},
'STAGE - load stage with custom shape using json': function(containerId) {
@ -228,7 +228,7 @@ Test.prototype.tests = {
context.closePath();
this.fillStroke();
};
var json = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":12,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"fill":"#00D2FF","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
var json = '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"fill":"#00D2FF","stroke":"black","strokeWidth":4,"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
stage.load(json);
var customShape = stage.get('#myTriangle')[0];
@ -1030,7 +1030,7 @@ Test.prototype.tests = {
var json = stage.toJSON();
test(json === '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":12,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"crop":{"x":0,"y":0},"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":200,"y":60,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":50,"y":150},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"darth"},"nodeType":"Shape","shapeType":"Image"}]}]}');
test(json === '{"attrs":{"width":578,"height":200,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"crop":{"x":0,"y":0},"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":200,"y":60,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":50,"y":150},"dragConstraint":"none","dragBounds":{},"draggable":false,"id":"darth"},"nodeType":"Shape","shapeType":"Image"}]}]}');
};
imageObj.src = '../darth-vader.jpg';
},
@ -2780,7 +2780,6 @@ Test.prototype.tests = {
var amplitude = 150;
var period = 1000;
// in ms
var centerX = 0;
stage.onFrame(function(frame) {
@ -2796,6 +2795,7 @@ Test.prototype.tests = {
test(go.animations.length === 0, 'should be no animations running');
test(stage.animRunning === false, 'animRunning should be false');
rect.transitionTo({
x: 300,
duration: 1,
@ -2810,6 +2810,6 @@ Test.prototype.tests = {
test(go.animations.length === 1, 'should be no animations running');
test(stage.animRunning === true, 'animRunning should be false');
}
});
});
}
};