|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
-
- /**
- * 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;
- };
|