added foundation for transition support, and added linear transitions. easeIn, easeOut, and easeInOut transitions will come later.

git status
This commit is contained in:
Eric Rowell 2012-03-12 22:41:09 -07:00
parent 0375fdc400
commit 1ac858dea5
8 changed files with 252 additions and 58 deletions

114
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: Mar 11 2012
* Date: Mar 12 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*
@ -70,10 +70,67 @@ Kinetic.GlobalObject = {
}
return false;
},
_endTransition: function() {
var config = this.config;
for(var key in config) {
if(config.hasOwnProperty(key)) {
this.node[key] = config[key];
this.node.getLayer().draw();
}
}
},
_linearTransition: function(frame) {
var config = this.config;
for(var key in config) {
if(config.hasOwnProperty(key)) {
this.node[key] += this.changes[key] * frame.timeDiff;
this.node.getLayer().draw();
}
}
},
_removeTransition: function(transition) {
var layer = transition.node.getLayer();
var id = transition.id;
for(var n = 0; n < layer.transitions.length; n++) {
if(layer.transitions[n].id === id) {
layer.transitions.splice(0, 1);
return false;
}
}
},
_runFrames: function() {
for(var n = 0; n < this.stages.length; n++) {
if(this.stages[n].isAnimating) {
this.stages[n].onFrameFunc(this.frame);
var stage = this.stages[n];
// run animation if available
if(stage.isAnimating && stage.onFrameFunc !== undefined) {
stage.onFrameFunc(this.frame);
}
/*
* run transitions
*/
// loop through layers
var layers = stage.getChildren();
for(var k = 0; k < layers.length; k++) {
var layer = layers[k];
var didTransition = false;
// loop through transitions
for(var i = 0; i < layer.transitions.length; i++) {
var transition = layer.transitions[i];
transition.time += this.frame.timeDiff;
if(transition.time >= transition.config.duration * 1000) {
this._endTransition.apply(transition);
this._removeTransition(transition);
} else {
didTransition = true;
this._linearTransition.apply(transition, [this.frame]);
}
}
if(didTransition) {
layer.draw();
}
}
}
},
@ -565,7 +622,11 @@ Kinetic.Node.prototype = {
* get stage associated to node
*/
getStage: function() {
return this.getParent().getStage();
if(this.className === 'Stage') {
return this;
} else {
return this.getParent().getStage();
}
},
/**
* get name
@ -588,6 +649,29 @@ Kinetic.Node.prototype = {
getCenterOffset: function() {
return this.centerOffset;
},
/**
* transition node to another state
* @param {Object} config
*/
transitionTo: function(config) {
var layer = this.getLayer();
var that = this;
var changes = {};
for(var key in config) {
if(config.hasOwnProperty(key)) {
changes[key] = (config[key] - that[key]) / (config.duration * 1000);
}
}
layer.transitions.push({
id: layer.transitionIdCounter++,
time: 0,
config: config,
node: this,
changes: changes
});
},
/**
* initialize drag and drop
*/
@ -784,11 +868,17 @@ Kinetic.Stage = function(cont, width, height) {
this.touchStart = false;
this.touchEnd = false;
// set stage id
this.id = Kinetic.GlobalObject.idCounter++;
// animation support
this.isAnimating = false;
this.onFrameFunc = undefined;
/*
* Layer roles
*
* buffer - canvas compositing
* backstage - path detection
* - buffer: canvas compositing
* - backstage: path detection
*/
this.bufferLayer = new Kinetic.Layer();
this.backstageLayer = new Kinetic.Layer();
@ -821,13 +911,6 @@ Kinetic.Stage = function(cont, width, height) {
var stages = Kinetic.GlobalObject.stages;
stages.push(this);
// set stage id
this.id = Kinetic.GlobalObject.idCounter++;
// animation support
this.isAnimating = false;
this.onFrameFunc = undefined;
// call super constructor
Kinetic.Container.apply(this, []);
};
@ -1397,6 +1480,8 @@ Kinetic.Layer = function(config) {
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute';
this.transitions = [];
this.transitionIdCounter = 0;
// call super constructors
Kinetic.Container.apply(this, []);
@ -1459,6 +1544,7 @@ Kinetic.Layer.prototype = {
// Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node);
///////////////////////////////////////////////////////////////////////
// Group
///////////////////////////////////////////////////////////////////////

File diff suppressed because one or more lines are too long

View File

@ -42,10 +42,67 @@ Kinetic.GlobalObject = {
}
return false;
},
_endTransition: function() {
var config = this.config;
for(var key in config) {
if(config.hasOwnProperty(key)) {
this.node[key] = config[key];
this.node.getLayer().draw();
}
}
},
_linearTransition: function(frame) {
var config = this.config;
for(var key in config) {
if(config.hasOwnProperty(key)) {
this.node[key] += this.changes[key] * frame.timeDiff;
this.node.getLayer().draw();
}
}
},
_removeTransition: function(transition) {
var layer = transition.node.getLayer();
var id = transition.id;
for(var n = 0; n < layer.transitions.length; n++) {
if(layer.transitions[n].id === id) {
layer.transitions.splice(0, 1);
return false;
}
}
},
_runFrames: function() {
for(var n = 0; n < this.stages.length; n++) {
if(this.stages[n].isAnimating) {
this.stages[n].onFrameFunc(this.frame);
var stage = this.stages[n];
// run animation if available
if(stage.isAnimating && stage.onFrameFunc !== undefined) {
stage.onFrameFunc(this.frame);
}
/*
* run transitions
*/
// loop through layers
var layers = stage.getChildren();
for(var k = 0; k < layers.length; k++) {
var layer = layers[k];
var didTransition = false;
// loop through transitions
for(var i = 0; i < layer.transitions.length; i++) {
var transition = layer.transitions[i];
transition.time += this.frame.timeDiff;
if(transition.time >= transition.config.duration * 1000) {
this._endTransition.apply(transition);
this._removeTransition(transition);
} else {
didTransition = true;
this._linearTransition.apply(transition, [this.frame]);
}
}
if(didTransition) {
layer.draw();
}
}
}
},

View File

@ -14,6 +14,8 @@ Kinetic.Layer = function(config) {
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute';
this.transitions = [];
this.transitionIdCounter = 0;
// call super constructors
Kinetic.Container.apply(this, []);
@ -75,4 +77,4 @@ Kinetic.Layer.prototype = {
};
// Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node);
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node);

View File

@ -445,7 +445,11 @@ Kinetic.Node.prototype = {
* get stage associated to node
*/
getStage: function() {
return this.getParent().getStage();
if(this.className === 'Stage') {
return this;
} else {
return this.getParent().getStage();
}
},
/**
* get name
@ -468,6 +472,29 @@ Kinetic.Node.prototype = {
getCenterOffset: function() {
return this.centerOffset;
},
/**
* transition node to another state
* @param {Object} config
*/
transitionTo: function(config) {
var layer = this.getLayer();
var that = this;
var changes = {};
for(var key in config) {
if(config.hasOwnProperty(key)) {
changes[key] = (config[key] - that[key]) / (config.duration * 1000);
}
}
layer.transitions.push({
id: layer.transitionIdCounter++,
time: 0,
config: config,
node: this,
changes: changes
});
},
/**
* initialize drag and drop
*/

View File

@ -33,11 +33,17 @@ Kinetic.Stage = function(cont, width, height) {
this.touchStart = false;
this.touchEnd = false;
// set stage id
this.id = Kinetic.GlobalObject.idCounter++;
// animation support
this.isAnimating = false;
this.onFrameFunc = undefined;
/*
* Layer roles
*
* buffer - canvas compositing
* backstage - path detection
* - buffer: canvas compositing
* - backstage: path detection
*/
this.bufferLayer = new Kinetic.Layer();
this.backstageLayer = new Kinetic.Layer();
@ -70,13 +76,6 @@ Kinetic.Stage = function(cont, width, height) {
var stages = Kinetic.GlobalObject.stages;
stages.push(this);
// set stage id
this.id = Kinetic.GlobalObject.idCounter++;
// animation support
this.isAnimating = false;
this.onFrameFunc = undefined;
// call super constructor
Kinetic.Container.apply(this, []);
};

View File

@ -2,6 +2,57 @@ function Test() {
this.testOnly = "";
this.counter = 0;
this.tests = {
"TRANSITION - transition position": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 10,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
rect.transitionTo({
x: 400,
y: 30,
rotation: Math.PI * 2,
duration: 1
});
},
"ANIMATION - run animation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 200,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
var amplitude = 150;
var period = 1000;
// in ms
var centerX = stage.width / 2 - 100 / 2;
stage.onFrame(function(frame) {
rect.x = amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX;
layer.draw();
});
stage.start();
},
"EVENTS - mousedown mouseup mouseover mouseout click dblclick / touchstart touchend dbltap": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();

View File

@ -1179,34 +1179,6 @@ function Test() {
test(stage.isAnimating === false, "stage should not be animating");
test(Kinetic.GlobalObject.isAnimating === false, "global object should not be animating");
},
"ANIMATION - run animation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 200,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
var amplitude = 150;
var period = 1000;
// in ms
var centerX = stage.width / 2 - 100 / 2;
stage.onFrame(function(frame) {
rect.x = amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX;
layer.draw();
});
stage.start();
}
};
}