/*
* timeline.js
*/
tm.namespace("tm.app", function() {
/**
* @class tm.app.Timeline
* タイムラインクラス
* @extends tm.event.EventDispatcher
*/
tm.define("tm.app.Timeline", {
superClass: "tm.app.Element",
/**
* @constructor
* @param {Object} elm
*/
init: function(elm) {
this.superInit();
this.setTarget(elm || {});
this.currentFrame = 0;
this.currentTime = 0;
this.prevTime = 0;
this.duration = 0;
this.isPlay = true;
this._tweens = [];
this._actions = [];
},
/**
* 更新
* @param {Object} app
*/
update: function(app) {
if (!this.isPlay) return ;
if (this.prevTime <= this.duration) {
this._updateTween();
this._updateAction();
}
this.currentFrame++;
this.prevTime = this.currentTime;
this.currentTime = ((this.currentFrame/app.fps)*1000)|0;
},
/**
* トゥイーンを更新
* @private
*/
_updateTween: function() {
var tweens = this._tweens;
for (var i=0,len=tweens.length; i<len; ++i) {
var tween = tweens[i];
if (tween.delay > this.currentTime) {
continue ;
}
var time = this.currentTime - tween.delay;
tween._setTime(time);
if (tween.time >= tween.duration) {
}
else {
tween.update();
}
}
},
/**
* アクションを更新
* @private
*/
_updateAction: function() {
var actions = this._actions;
for (var i=0,len=actions.length; i<len; ++i) {
var action = actions[i];
if (this.prevTime <= action.delay && action.delay < this.currentTime) {
if (action.type == "call") {
action.func.call(action.self);
// action.func();
}
else if (action.type == "set") {
var props = action.props;
for (var key in props) {
this.element[key] = props[key];
}
}
}
}
},
/**
* 指定した値までアニメーション
* @param {Object} delay
* @param {Object} props
* @param {Object} duration
* @param {Function} func
*/
to: function(delay, props, duration, fn) {
console.assert(typeof delay == "number", "to の第一引数はdelayに変わりました");
this._addTween({
props: props,
duration: duration,
fn: fn,
delay: delay
});
return this;
},
/**
* 指定した値を足した値までアニメーション
* @param {Object} delay
* @param {Object} props
* @param {Object} duration
* @param {Function} func
*/
by: function(delay, props, duration, fn) {
console.assert(typeof delay == "number", "by の第一引数はdelayに変わりました");
for (var key in props) {
props[key] += this.element[key] || 0;
}
this._addTween({
props: props,
duration: duration,
fn: fn,
delay: delay
});
return this;
},
/**
* 関数を実行
* @param {Object} delay
* @param {Function} func
*/
call: function(delay, func, self) {
console.assert(typeof delay == "number", "call の第一引数はdelayに変わりました");
this._addAction({
"type": "call",
func: func,
self: self || this,
delay: delay,
});
return this;
},
/**
* プロパティをセット
* @param {Object} delay
* @param {Object} props
*/
set: function(delay, props) {
console.assert(typeof delay == "number", "set の第一引数はdelayに変わりました");
this._addAction({
"type": "set",
props: props,
delay: delay,
});
return this;
},
/**
* ターゲットのセット
* @param {Object} target
*/
setTarget: function(target) {
this.element = target;
return this;
},
/**
* ターゲットをゲット
*/
getTarget: function() {
return this.element;
},
/**
* アニメーション開始
* アニメーションが終了したら再度アニメーションを行う
* @param {Number} frame
*/
gotoAndPlay: function(frame) {
this.isPlay = true;
this.currentFrame = frame;
this._updateTween();
},
/**
* アニメーション開始
* アニメーションが終了したらストップする
* @param {Number} frame
*/
gotoAndStop: function(frame) {
this.currentFrame = frame;
this.isPlay = false;
this._updateTween();
},
/**
* tween を追加
* @private
* @param {Object} tween
*/
_addTween: function(tween) {
tween.duration = tween.duration || 1000;
tween.duration = this._dirty(tween.duration);
tween.delay = tween.delay || 0;
tween.delay = this._dirty(tween.delay);
var tweenObj = tm.anim.Tween();
tweenObj.to(this.element, tween.props, tween.duration, tween.fn);
tweenObj.delay = tween.delay;
this._tweens.push(tweenObj);
this._updateDuration(tweenObj);
},
/**
* アニメーションを追加
* @private
* @param {Object} action
*/
_addAction: function(action) {
action.delay = action.delay || 0;
action.delay = this._dirty(action.delay);
this._actions.push(action);
this._updateDuration(action);
},
/**
* 時間を更新
* @private
* @param {Object} task
*/
_updateDuration: function(task) {
var duration = task.delay + (task.duration ? task.duration : 0);
if (this.duration < duration) this.duration = duration;
return this;
},
/**
* dirty method
* @private
* @param {Object} t
*/
_dirty: function(t) {
return t;
// return (t/this.fps).toInt();
},
/**
* ロード
* @param {Object} data
*/
load: function(data) {
for (var key in data.timeline) {
var value = data.timeline[key];
}
return this;
},
/**
* アニメーションをクリア
*/
clear: function() {
this.currentFrame = 0;
this.prevTime = 0;
this.currentTime = 0;
this.duration = 0;
this.isPlay = true;
this._tweens = [];
this._actions = [];
return this;
}
});
/**
* @member tm.app.Element
* @property timeline
* タイムラインアニメーション
*/
tm.app.Element.prototype.getter("timeline", function() {
if (!this._timeline) {
this._timeline = tm.app.Timeline(this);
this.on("enterframe", function(e) {
this._timeline.update(e.app);
});
}
return this._timeline;
});
});