implement pinch to zoom
This commit is contained in:
+178
@@ -0,0 +1,178 @@
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
Reference in New Issue
Block a user