178 lines
2.9 KiB
JavaScript
178 lines
2.9 KiB
JavaScript
|
|||
|
|
/**
|
||
|
|
* Module dependencies.
|
||
|
|
*/
|
||
|
|
|
||
|
|
var Emitter = require('emitter');
|
||
|
|
var clone = require('clone');
|
||
|
|
var type = require('type');
|
||
|
|
var ease = require('ease');
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Expose `Tween`.
|
||
|
|
*/
|
||
|
|
|
||
|
|
module.exports = Tween;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize a new `Tween` with `obj`.
|
||
|
|
*
|
||
|
|
* @param {Object|Array} obj
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
function Tween(obj) {
|
||
|
|
if (!(this instanceof Tween)) return new Tween(obj);
|
||
|
|
this._from = obj;
|
||
|
|
this.ease('linear');
|
||
|
|
this.duration(500);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Mixin emitter.
|
||
|
|
*/
|
||
|
|
|
||
|
|
Emitter(Tween.prototype);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Reset the tween.
|
||
|
|
*
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.reset = function(){
|
||
|
|
this.isArray = 'array' === type(this._from);
|
||
|
|
this._curr = clone(this._from);
|
||
|
|
this._done = false;
|
||
|
|
this._start = Date.now();
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Tween to `obj` and reset internal state.
|
||
|
|
*
|
||
|
|
* tween.to({ x: 50, y: 100 })
|
||
|
|
*
|
||
|
|
* @param {Object|Array} obj
|
||
|
|
* @return {Tween} self
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.to = function(obj){
|
||
|
|
this.reset();
|
||
|
|
this._to = obj;
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set duration to `ms` [500].
|
||
|
|
*
|
||
|
|
* @param {Number} ms
|
||
|
|
* @return {Tween} self
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.duration = function(ms){
|
||
|
|
this._duration = ms;
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set easing function to `fn`.
|
||
|
|
*
|
||
|
|
* tween.ease('in-out-sine')
|
||
|
|
*
|
||
|
|
* @param {String|Function} fn
|
||
|
|
* @return {Tween}
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.ease = function(fn){
|
||
|
|
fn = 'function' == typeof fn ? fn : ease[fn];
|
||
|
|
if (!fn) throw new TypeError('invalid easing function');
|
||
|
|
this._ease = fn;
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Stop the tween and immediately emit "stop" and "end".
|
||
|
|
*
|
||
|
|
* @return {Tween}
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.stop = function(){
|
||
|
|
this.stopped = true;
|
||
|
|
this._done = true;
|
||
|
|
this.emit('stop');
|
||
|
|
this.emit('end');
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Perform a step.
|
||
|
|
*
|
||
|
|
* @return {Tween} self
|
||
|
|
* @api private
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.step = function(){
|
||
|
|
if (this._done) return;
|
||
|
|
|
||
|
|
// duration
|
||
|
|
var duration = this._duration;
|
||
|
|
var now = Date.now();
|
||
|
|
var delta = now - this._start;
|
||
|
|
var done = delta >= duration;
|
||
|
|
|
||
|
|
// complete
|
||
|
|
if (done) {
|
||
|
|
this._from = this._to;
|
||
|
|
this._update(this._to);
|
||
|
|
this._done = true;
|
||
|
|
this.emit('end');
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
// tween
|
||
|
|
var from = this._from;
|
||
|
|
var to = this._to;
|
||
|
|
var curr = this._curr;
|
||
|
|
var fn = this._ease;
|
||
|
|
var p = (now - this._start) / duration;
|
||
|
|
var n = fn(p);
|
||
|
|
|
||
|
|
// array
|
||
|
|
if (this.isArray) {
|
||
|
|
for (var i = 0; i < from.length; ++i) {
|
||
|
|
curr[i] = from[i] + (to[i] - from[i]) * n;
|
||
|
|
}
|
||
|
|
|
||
|
|
this._update(curr);
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
// objech
|
||
|
|
for (var k in from) {
|
||
|
|
curr[k] = from[k] + (to[k] - from[k]) * n;
|
||
|
|
}
|
||
|
|
|
||
|
|
this._update(curr);
|
||
|
|
return this;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set update function to `fn` or
|
||
|
|
* when no argument is given this performs
|
||
|
|
* a "step".
|
||
|
|
*
|
||
|
|
* @param {Function} fn
|
||
|
|
* @return {Tween} self
|
||
|
|
* @api public
|
||
|
|
*/
|
||
|
|
|
||
|
|
Tween.prototype.update = function(fn){
|
||
|
|
if (0 == arguments.length) return this.step();
|
||
|
|
this._update = fn;
|
||
|
|
return this;
|
||
|
|
};
|