UNPKG

component-tween

Version:

Motion tween engine using 'ease'

178 lines (149 loc) 2.92 kB
/** * 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; };