react-animation-engine
Version:
Extract famo.us transitionable capabilities in 14kb for react. Mixin to transition between state values.
1,564 lines (1,486 loc) • 269 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define(factory);
else if(typeof exports === 'object')
exports["FamousAnimations"] = factory();
else
root["FamousAnimations"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
Object.defineProperty(exports, '__esModule', {
value: true
});
var _TransitionableMixin = __webpack_require__(1);
var _TransitionableMixin2 = _interopRequireWildcard(_TransitionableMixin);
var _Transitionable = __webpack_require__(2);
var _Transitionable2 = _interopRequireWildcard(_Transitionable);
var _Easing = __webpack_require__(3);
var _Easing2 = _interopRequireWildcard(_Easing);
var SpringTransition = __webpack_require__(4);
var WallTransition = __webpack_require__(5);
var SnapTransition = __webpack_require__(6);
_Transitionable2['default'].registerMethod('spring', SpringTransition);
_Transitionable2['default'].registerMethod('wall', WallTransition);
_Transitionable2['default'].registerMethod('snap', SnapTransition);
exports.TransitionableMixin = _TransitionableMixin2['default'];
exports.Transitionable = _Transitionable2['default'];
exports.Easing = _Easing2['default'];
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
var _defineProperty = function (obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: key == null || typeof Symbol == 'undefined' || key.constructor !== Symbol, configurable: true, writable: true }); };
Object.defineProperty(exports, '__esModule', {
value: true
});
var _Transitionable = __webpack_require__(2);
var _Transitionable2 = _interopRequireWildcard(_Transitionable);
var _Easing = __webpack_require__(3);
var _Easing2 = _interopRequireWildcard(_Easing);
function TransitionableMixin(props) {
props = [].concat(props);
var _transitionables = {};
var mixin = {
componentWillUnmount: function componentWillUnmount() {
props.forEach(function (p) {
delete _transitionables[p];
});
},
componentWillMount: function componentWillMount() {
var _this = this;
props.forEach(function (p) {
// Create a transitionable
_transitionables[p] = new _Transitionable2['default'](_this.state[p]);
// Define a property
var property = p;
Object.defineProperty(_this, property, {
get: function get() {
return _transitionables[property].get();
},
set: function set(v) {
/* {value, duration , animation} */
if (typeof v != 'object') {
v = { value: v };
}
// Store the value
var value = v.value;
delete v.value;
// Use 'inSine' as default curve
if (!v.curve) {
v.curve = _Easing2['default'].inSine;
}
this.tween(property, value, v);
}
});
var trans = _transitionables[property];
trans.update(_this._syncProp.bind(_this, property));
_this._syncProp(property);
});
},
_syncProp: function _syncProp(prop) {
var trans = _transitionables[prop];
var state = _defineProperty({}, prop, trans.get());
this.setState(state);
},
tween: function tween(prop, value, animation, callback) {
var trans = _transitionables[prop];
trans.val(value, animation, callback);
},
halt: function halt(prop) {
if (prop) {
var trans = _transitionables[p];
trans.halt();
return;
} else {
props.forEach(function (p) {
var trans = _transitionables[p];
trans.halt();
});
}
}
};
return mixin;
}
exports['default'] = TransitionableMixin;
module.exports = exports['default'];
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } };
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
var FamousTransitionable = __webpack_require__(7);
var allowAnimations = false;
var animationID = null;
var transitionables = [];
var listeners = [];
function haveAllFinishedAnimating() {
return transitionables.map(function (t) {
return t._isAnimating;
}).reduce(function (final, tIsAnimating) {
return final && !tIsAnimating;
}, true);
}
function executeListeners() {
for (var ls in listeners) {
listeners[ls]();
}
}
function requestCancelation() {
if (haveAllFinishedAnimating()) {
cancelAnimationFrame(animationID);
allowAnimations = false;
animationID = null;
}
}
// Setup animation
function animate() {
if (!allowAnimations) {
return;
}executeListeners();
animationID = requestAnimationFrame(animate);
}
var Transitionable = (function (_FamousTransitionable) {
function Transitionable(value) {
var _this = this;
_classCallCheck(this, Transitionable);
_get(Object.getPrototypeOf(Transitionable.prototype), 'constructor', this).call(this, value);
// Configure for globals
transitionables.push(this);
this._listenerFn = function () {
return _this._executeListeners();
};
listeners.push(this._listenerFn);
this._isAnimating = false;
}
_inherits(Transitionable, _FamousTransitionable);
_createClass(Transitionable, [{
key: 'update',
value: function update(fn) {
this._listeners = this._listeners || [];
this._listeners.push(fn);
}
}, {
key: 'val',
value: function val(value, animation, complete) {
var self = this;
// Call the original set
self.set(value, animation, function () {
// Last time execution
if (animationID) {
self._isAnimating = false;
}
requestCancelation();
if (complete) {
complete();
};
});
// Prepare for animation
allowAnimations = true;
// Request animation start
if (haveAllFinishedAnimating()) animate();
self._isAnimating = true;
}
}, {
key: '_executeListeners',
value: function _executeListeners() {
var _this2 = this;
// Execute listeners
if (this._listeners) {
this._listeners.forEach(function (fn) {
return fn(_this2.get());
});
}
}
}]);
return Transitionable;
})(FamousTransitionable);
module.exports = Transitionable;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var Easing = {
inQuad: function (t) {
return t * t;
},
outQuad: function (t) {
return -(t -= 1) * t + 1;
},
inOutQuad: function (t) {
if ((t /= 0.5) < 1)
return 0.5 * t * t;
return -0.5 * (--t * (t - 2) - 1);
},
inCubic: function (t) {
return t * t * t;
},
outCubic: function (t) {
return --t * t * t + 1;
},
inOutCubic: function (t) {
if ((t /= 0.5) < 1)
return 0.5 * t * t * t;
return 0.5 * ((t -= 2) * t * t + 2);
},
inQuart: function (t) {
return t * t * t * t;
},
outQuart: function (t) {
return -(--t * t * t * t - 1);
},
inOutQuart: function (t) {
if ((t /= 0.5) < 1)
return 0.5 * t * t * t * t;
return -0.5 * ((t -= 2) * t * t * t - 2);
},
inQuint: function (t) {
return t * t * t * t * t;
},
outQuint: function (t) {
return --t * t * t * t * t + 1;
},
inOutQuint: function (t) {
if ((t /= 0.5) < 1)
return 0.5 * t * t * t * t * t;
return 0.5 * ((t -= 2) * t * t * t * t + 2);
},
inSine: function (t) {
return -1 * Math.cos(t * (Math.PI / 2)) + 1;
},
outSine: function (t) {
return Math.sin(t * (Math.PI / 2));
},
inOutSine: function (t) {
return -0.5 * (Math.cos(Math.PI * t) - 1);
},
inExpo: function (t) {
return t === 0 ? 0 : Math.pow(2, 10 * (t - 1));
},
outExpo: function (t) {
return t === 1 ? 1 : -Math.pow(2, -10 * t) + 1;
},
inOutExpo: function (t) {
if (t === 0)
return 0;
if (t === 1)
return 1;
if ((t /= 0.5) < 1)
return 0.5 * Math.pow(2, 10 * (t - 1));
return 0.5 * (-Math.pow(2, -10 * --t) + 2);
},
inCirc: function (t) {
return -(Math.sqrt(1 - t * t) - 1);
},
outCirc: function (t) {
return Math.sqrt(1 - --t * t);
},
inOutCirc: function (t) {
if ((t /= 0.5) < 1)
return -0.5 * (Math.sqrt(1 - t * t) - 1);
return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
},
inElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0)
return 0;
if (t === 1)
return 1;
if (!p)
p = 0.3;
s = p / (2 * Math.PI) * Math.asin(1 / a);
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
},
outElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0)
return 0;
if (t === 1)
return 1;
if (!p)
p = 0.3;
s = p / (2 * Math.PI) * Math.asin(1 / a);
return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;
},
inOutElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0)
return 0;
if ((t /= 0.5) === 2)
return 1;
if (!p)
p = 0.3 * 1.5;
s = p / (2 * Math.PI) * Math.asin(1 / a);
if (t < 1)
return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;
},
inBack: function (t, s) {
if (s === undefined)
s = 1.70158;
return t * t * ((s + 1) * t - s);
},
outBack: function (t, s) {
if (s === undefined)
s = 1.70158;
return --t * t * ((s + 1) * t + s) + 1;
},
inOutBack: function (t, s) {
if (s === undefined)
s = 1.70158;
if ((t /= 0.5) < 1)
return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));
return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);
},
inBounce: function (t) {
return 1 - Easing.outBounce(1 - t);
},
outBounce: function (t) {
if (t < 1 / 2.75) {
return 7.5625 * t * t;
} else if (t < 2 / 2.75) {
return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
} else if (t < 2.5 / 2.75) {
return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
} else {
return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
}
},
inOutBounce: function (t) {
if (t < 0.5)
return Easing.inBounce(t * 2) * 0.5;
return Easing.outBounce(t * 2 - 1) * 0.5 + 0.5;
}
};
module.exports = Easing;
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var PE = __webpack_require__(8);
var Particle = __webpack_require__(9);
var Spring = __webpack_require__(10);
var Vector = __webpack_require__(12);
function SpringTransition(state) {
state = state || 0;
this.endState = new Vector(state);
this.initState = new Vector();
this._dimensions = undefined;
this._restTolerance = 1e-10;
this._absRestTolerance = this._restTolerance;
this._callback = undefined;
this.PE = new PE();
this.spring = new Spring({ anchor: this.endState });
this.particle = new Particle();
this.PE.addBody(this.particle);
this.PE.attach(this.spring, this.particle);
}
SpringTransition.SUPPORTS_MULTIPLE = 3;
SpringTransition.DEFAULT_OPTIONS = {
period: 300,
dampingRatio: 0.5,
velocity: 0
};
function _getEnergy() {
return this.particle.getEnergy() + this.spring.getEnergy([this.particle]);
}
function _setParticlePosition(p) {
this.particle.setPosition(p);
}
function _setParticleVelocity(v) {
this.particle.setVelocity(v);
}
function _getParticlePosition() {
return this._dimensions === 0 ? this.particle.getPosition1D() : this.particle.getPosition();
}
function _getParticleVelocity() {
return this._dimensions === 0 ? this.particle.getVelocity1D() : this.particle.getVelocity();
}
function _setCallback(callback) {
this._callback = callback;
}
function _wake() {
this.PE.wake();
}
function _sleep() {
this.PE.sleep();
}
function _update() {
if (this.PE.isSleeping()) {
if (this._callback) {
var cb = this._callback;
this._callback = undefined;
cb();
}
return;
}
if (_getEnergy.call(this) < this._absRestTolerance) {
_setParticlePosition.call(this, this.endState);
_setParticleVelocity.call(this, [
0,
0,
0
]);
_sleep.call(this);
}
}
function _setupDefinition(definition) {
var defaults = SpringTransition.DEFAULT_OPTIONS;
if (definition.period === undefined)
definition.period = defaults.period;
if (definition.dampingRatio === undefined)
definition.dampingRatio = defaults.dampingRatio;
if (definition.velocity === undefined)
definition.velocity = defaults.velocity;
if (definition.period < 150) {
definition.period = 150;
console.warn('The period of a SpringTransition is capped at 150 ms. Use a SnapTransition for faster transitions');
}
this.spring.setOptions({
period: definition.period,
dampingRatio: definition.dampingRatio
});
_setParticleVelocity.call(this, definition.velocity);
}
function _setAbsoluteRestTolerance() {
var distance = this.endState.sub(this.initState).normSquared();
this._absRestTolerance = distance === 0 ? this._restTolerance : this._restTolerance * distance;
}
function _setTarget(target) {
this.endState.set(target);
_setAbsoluteRestTolerance.call(this);
}
SpringTransition.prototype.reset = function reset(pos, vel) {
this._dimensions = pos instanceof Array ? pos.length : 0;
this.initState.set(pos);
_setParticlePosition.call(this, pos);
_setTarget.call(this, pos);
if (vel)
_setParticleVelocity.call(this, vel);
_setCallback.call(this, undefined);
};
SpringTransition.prototype.getVelocity = function getVelocity() {
return _getParticleVelocity.call(this);
};
SpringTransition.prototype.setVelocity = function setVelocity(v) {
this.call(this, _setParticleVelocity(v));
};
SpringTransition.prototype.isActive = function isActive() {
return !this.PE.isSleeping();
};
SpringTransition.prototype.halt = function halt() {
this.set(this.get());
};
SpringTransition.prototype.get = function get() {
_update.call(this);
return _getParticlePosition.call(this);
};
SpringTransition.prototype.set = function set(endState, definition, callback) {
if (!definition) {
this.reset(endState);
if (callback)
callback();
return;
}
this._dimensions = endState instanceof Array ? endState.length : 0;
_wake.call(this);
_setupDefinition.call(this, definition);
_setTarget.call(this, endState);
_setCallback.call(this, callback);
};
module.exports = SpringTransition;
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var PE = __webpack_require__(8);
var Particle = __webpack_require__(9);
var Spring = __webpack_require__(10);
var Wall = __webpack_require__(11);
var Vector = __webpack_require__(12);
function WallTransition(state) {
state = state || 0;
this.endState = new Vector(state);
this.initState = new Vector();
this.spring = new Spring({ anchor: this.endState });
this.wall = new Wall();
this._restTolerance = 1e-10;
this._dimensions = 1;
this._absRestTolerance = this._restTolerance;
this._callback = undefined;
this.PE = new PE();
this.particle = new Particle();
this.PE.addBody(this.particle);
this.PE.attach([
this.wall,
this.spring
], this.particle);
}
WallTransition.SUPPORTS_MULTIPLE = 3;
WallTransition.DEFAULT_OPTIONS = {
period: 300,
dampingRatio: 0.5,
velocity: 0,
restitution: 0.5
};
function _getEnergy() {
return this.particle.getEnergy() + this.spring.getEnergy([this.particle]);
}
function _setAbsoluteRestTolerance() {
var distance = this.endState.sub(this.initState).normSquared();
this._absRestTolerance = distance === 0 ? this._restTolerance : this._restTolerance * distance;
}
function _wake() {
this.PE.wake();
}
function _sleep() {
this.PE.sleep();
}
function _setTarget(target) {
this.endState.set(target);
var dist = this.endState.sub(this.initState).norm();
this.wall.setOptions({
distance: this.endState.norm(),
normal: dist === 0 ? this.particle.velocity.normalize(-1) : this.endState.sub(this.initState).normalize(-1)
});
_setAbsoluteRestTolerance.call(this);
}
function _setParticlePosition(p) {
this.particle.position.set(p);
}
function _setParticleVelocity(v) {
this.particle.velocity.set(v);
}
function _getParticlePosition() {
return this._dimensions === 0 ? this.particle.getPosition1D() : this.particle.getPosition();
}
function _getParticleVelocity() {
return this._dimensions === 0 ? this.particle.getVelocity1D() : this.particle.getVelocity();
}
function _setCallback(callback) {
this._callback = callback;
}
function _update() {
if (this.PE.isSleeping()) {
if (this._callback) {
var cb = this._callback;
this._callback = undefined;
cb();
}
return;
}
var energy = _getEnergy.call(this);
if (energy < this._absRestTolerance) {
_sleep.call(this);
_setParticlePosition.call(this, this.endState);
_setParticleVelocity.call(this, [
0,
0,
0
]);
}
}
function _setupDefinition(def) {
var defaults = WallTransition.DEFAULT_OPTIONS;
if (def.period === undefined)
def.period = defaults.period;
if (def.dampingRatio === undefined)
def.dampingRatio = defaults.dampingRatio;
if (def.velocity === undefined)
def.velocity = defaults.velocity;
if (def.restitution === undefined)
def.restitution = defaults.restitution;
if (def.drift === undefined)
def.drift = Wall.DEFAULT_OPTIONS.drift;
if (def.slop === undefined)
def.slop = Wall.DEFAULT_OPTIONS.slop;
this.spring.setOptions({
period: def.period,
dampingRatio: def.dampingRatio
});
this.wall.setOptions({
restitution: def.restitution,
drift: def.drift,
slop: def.slop
});
_setParticleVelocity.call(this, def.velocity);
}
WallTransition.prototype.reset = function reset(state, velocity) {
this._dimensions = state instanceof Array ? state.length : 0;
this.initState.set(state);
_setParticlePosition.call(this, state);
if (velocity)
_setParticleVelocity.call(this, velocity);
_setTarget.call(this, state);
_setCallback.call(this, undefined);
};
WallTransition.prototype.getVelocity = function getVelocity() {
return _getParticleVelocity.call(this);
};
WallTransition.prototype.setVelocity = function setVelocity(velocity) {
this.call(this, _setParticleVelocity(velocity));
};
WallTransition.prototype.isActive = function isActive() {
return !this.PE.isSleeping();
};
WallTransition.prototype.halt = function halt() {
this.set(this.get());
};
WallTransition.prototype.get = function get() {
_update.call(this);
return _getParticlePosition.call(this);
};
WallTransition.prototype.set = function set(state, definition, callback) {
if (!definition) {
this.reset(state);
if (callback)
callback();
return;
}
this._dimensions = state instanceof Array ? state.length : 0;
_wake.call(this);
_setupDefinition.call(this, definition);
_setTarget.call(this, state);
_setCallback.call(this, callback);
};
module.exports = WallTransition;
/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var PE = __webpack_require__(8);
var Particle = __webpack_require__(9);
var Spring = __webpack_require__(13);
var Vector = __webpack_require__(12);
function SnapTransition(state) {
state = state || 0;
this.endState = new Vector(state);
this.initState = new Vector();
this._dimensions = 1;
this._restTolerance = 1e-10;
this._absRestTolerance = this._restTolerance;
this._callback = undefined;
this.PE = new PE();
this.particle = new Particle();
this.spring = new Spring({ anchor: this.endState });
this.PE.addBody(this.particle);
this.PE.attach(this.spring, this.particle);
}
SnapTransition.SUPPORTS_MULTIPLE = 3;
SnapTransition.DEFAULT_OPTIONS = {
period: 100,
dampingRatio: 0.2,
velocity: 0
};
function _getEnergy() {
return this.particle.getEnergy() + this.spring.getEnergy([this.particle]);
}
function _setAbsoluteRestTolerance() {
var distance = this.endState.sub(this.initState).normSquared();
this._absRestTolerance = distance === 0 ? this._restTolerance : this._restTolerance * distance;
}
function _setTarget(target) {
this.endState.set(target);
_setAbsoluteRestTolerance.call(this);
}
function _wake() {
this.PE.wake();
}
function _sleep() {
this.PE.sleep();
}
function _setParticlePosition(p) {
this.particle.position.set(p);
}
function _setParticleVelocity(v) {
this.particle.velocity.set(v);
}
function _getParticlePosition() {
return this._dimensions === 0 ? this.particle.getPosition1D() : this.particle.getPosition();
}
function _getParticleVelocity() {
return this._dimensions === 0 ? this.particle.getVelocity1D() : this.particle.getVelocity();
}
function _setCallback(callback) {
this._callback = callback;
}
function _setupDefinition(definition) {
var defaults = SnapTransition.DEFAULT_OPTIONS;
if (definition.period === undefined)
definition.period = defaults.period;
if (definition.dampingRatio === undefined)
definition.dampingRatio = defaults.dampingRatio;
if (definition.velocity === undefined)
definition.velocity = defaults.velocity;
this.spring.setOptions({
period: definition.period,
dampingRatio: definition.dampingRatio
});
_setParticleVelocity.call(this, definition.velocity);
}
function _update() {
if (this.PE.isSleeping()) {
if (this._callback) {
var cb = this._callback;
this._callback = undefined;
cb();
}
return;
}
if (_getEnergy.call(this) < this._absRestTolerance) {
_setParticlePosition.call(this, this.endState);
_setParticleVelocity.call(this, [
0,
0,
0
]);
_sleep.call(this);
}
}
SnapTransition.prototype.reset = function reset(state, velocity) {
this._dimensions = state instanceof Array ? state.length : 0;
this.initState.set(state);
_setParticlePosition.call(this, state);
_setTarget.call(this, state);
if (velocity)
_setParticleVelocity.call(this, velocity);
_setCallback.call(this, undefined);
};
SnapTransition.prototype.getVelocity = function getVelocity() {
return _getParticleVelocity.call(this);
};
SnapTransition.prototype.setVelocity = function setVelocity(velocity) {
this.call(this, _setParticleVelocity(velocity));
};
SnapTransition.prototype.isActive = function isActive() {
return !this.PE.isSleeping();
};
SnapTransition.prototype.halt = function halt() {
this.set(this.get());
};
SnapTransition.prototype.get = function get() {
_update.call(this);
return _getParticlePosition.call(this);
};
SnapTransition.prototype.set = function set(state, definition, callback) {
if (!definition) {
this.reset(state);
if (callback)
callback();
return;
}
this._dimensions = state instanceof Array ? state.length : 0;
_wake.call(this);
_setupDefinition.call(this, definition);
_setTarget.call(this, state);
_setCallback.call(this, callback);
};
module.exports = SnapTransition;
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var MultipleTransition = __webpack_require__(14);
var TweenTransition = __webpack_require__(15);
function Transitionable(start) {
this.currentAction = null;
this.actionQueue = [];
this.callbackQueue = [];
this.state = 0;
this.velocity = undefined;
this._callback = undefined;
this._engineInstance = null;
this._currentMethod = null;
this.set(start);
}
var transitionMethods = {};
Transitionable.register = function register(methods) {
var success = true;
for (var method in methods) {
if (!Transitionable.registerMethod(method, methods[method]))
success = false;
}
return success;
};
Transitionable.registerMethod = function registerMethod(name, engineClass) {
if (!(name in transitionMethods)) {
transitionMethods[name] = engineClass;
return true;
} else
return false;
};
Transitionable.unregisterMethod = function unregisterMethod(name) {
if (name in transitionMethods) {
delete transitionMethods[name];
return true;
} else
return false;
};
function _loadNext() {
if (this._callback) {
var callback = this._callback;
this._callback = undefined;
callback();
}
if (this.actionQueue.length <= 0) {
this.set(this.get());
return;
}
this.currentAction = this.actionQueue.shift();
this._callback = this.callbackQueue.shift();
var method = null;
var endValue = this.currentAction[0];
var transition = this.currentAction[1];
if (transition instanceof Object && transition.method) {
method = transition.method;
if (typeof method === 'string')
method = transitionMethods[method];
} else {
method = TweenTransition;
}
if (this._currentMethod !== method) {
if (!(endValue instanceof Object) || method.SUPPORTS_MULTIPLE === true || endValue.length <= method.SUPPORTS_MULTIPLE) {
this._engineInstance = new method();
} else {
this._engineInstance = new MultipleTransition(method);
}
this._currentMethod = method;
}
this._engineInstance.reset(this.state, this.velocity);
if (this.velocity !== undefined)
transition.velocity = this.velocity;
this._engineInstance.set(endValue, transition, _loadNext.bind(this));
}
Transitionable.prototype.set = function set(endState, transition, callback) {
if (!transition) {
this.reset(endState);
if (callback)
callback();
return this;
}
var action = [
endState,
transition
];
this.actionQueue.push(action);
this.callbackQueue.push(callback);
if (!this.currentAction)
_loadNext.call(this);
return this;
};
Transitionable.prototype.reset = function reset(startState, startVelocity) {
this._currentMethod = null;
this._engineInstance = null;
this._callback = undefined;
this.state = startState;
this.velocity = startVelocity;
this.currentAction = null;
this.actionQueue = [];
this.callbackQueue = [];
};
Transitionable.prototype.delay = function delay(duration, callback) {
var endValue;
if (this.actionQueue.length)
endValue = this.actionQueue[this.actionQueue.length - 1][0];
else if (this.currentAction)
endValue = this.currentAction[0];
else
endValue = this.get();
return this.set(endValue, {
duration: duration,
curve: function () {
return 0;
}
}, callback);
};
Transitionable.prototype.get = function get(timestamp) {
if (this._engineInstance) {
if (this._engineInstance.getVelocity)
this.velocity = this._engineInstance.getVelocity();
this.state = this._engineInstance.get(timestamp);
}
return this.state;
};
Transitionable.prototype.isActive = function isActive() {
return !!this.currentAction;
};
Transitionable.prototype.halt = function halt() {
return this.set(this.get());
};
module.exports = Transitionable;
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var EventHandler = __webpack_require__(16);
function PhysicsEngine(options) {
this.options = Object.create(PhysicsEngine.DEFAULT_OPTIONS);
if (options)
this.setOptions(options);
this._particles = [];
this._bodies = [];
this._agentData = {};
this._forces = [];
this._constraints = [];
this._buffer = 0;
this._prevTime = now();
this._isSleeping = false;
this._eventHandler = null;
this._currAgentId = 0;
this._hasBodies = false;
this._eventHandler = null;
}
var TIMESTEP = 17;
var MIN_TIME_STEP = 1000 / 120;
var MAX_TIME_STEP = 17;
var now = Date.now;
var _events = {
start: 'start',
update: 'update',
end: 'end'
};
PhysicsEngine.DEFAULT_OPTIONS = {
constraintSteps: 1,
sleepTolerance: 1e-7,
velocityCap: undefined,
angularVelocityCap: undefined
};
PhysicsEngine.prototype.setOptions = function setOptions(opts) {
for (var key in opts)
if (this.options[key])
this.options[key] = opts[key];
};
PhysicsEngine.prototype.addBody = function addBody(body) {
body._engine = this;
if (body.isBody) {
this._bodies.push(body);
this._hasBodies = true;
} else
this._particles.push(body);
body.on('start', this.wake.bind(this));
return body;
};
PhysicsEngine.prototype.removeBody = function removeBody(body) {
var array = body.isBody ? this._bodies : this._particles;
var index = array.indexOf(body);
if (index > -1) {
for (var agentKey in this._agentData) {
if (this._agentData.hasOwnProperty(agentKey)) {
this.detachFrom(this._agentData[agentKey].id, body);
}
}
array.splice(index, 1);
}
if (this.getBodies().length === 0)
this._hasBodies = false;
};
function _mapAgentArray(agent) {
if (agent.applyForce)
return this._forces;
if (agent.applyConstraint)
return this._constraints;
}
function _attachOne(agent, targets, source) {
if (targets === undefined)
targets = this.getParticlesAndBodies();
if (!(targets instanceof Array))
targets = [targets];
agent.on('change', this.wake.bind(this));
this._agentData[this._currAgentId] = {
agent: agent,
id: this._currAgentId,
targets: targets,
source: source
};
_mapAgentArray.call(this, agent).push(this._currAgentId);
return this._currAgentId++;
}
PhysicsEngine.prototype.attach = function attach(agents, targets, source) {
this.wake();
if (agents instanceof Array) {
var agentIDs = [];
for (var i = 0; i < agents.length; i++)
agentIDs[i] = _attachOne.call(this, agents[i], targets, source);
return agentIDs;
} else
return _attachOne.call(this, agents, targets, source);
};
PhysicsEngine.prototype.attachTo = function attachTo(agentID, target) {
_getAgentData.call(this, agentID).targets.push(target);
};
PhysicsEngine.prototype.detach = function detach(id) {
var agent = this.getAgent(id);
var agentArray = _mapAgentArray.call(this, agent);
var index = agentArray.indexOf(id);
agentArray.splice(index, 1);
delete this._agentData[id];
};
PhysicsEngine.prototype.detachFrom = function detachFrom(id, target) {
var boundAgent = _getAgentData.call(this, id);
if (boundAgent.source === target)
this.detach(id);
else {
var targets = boundAgent.targets;
var index = targets.indexOf(target);
if (index > -1)
targets.splice(index, 1);
}
};
PhysicsEngine.prototype.detachAll = function detachAll() {
this._agentData = {};
this._forces = [];
this._constraints = [];
this._currAgentId = 0;
};
function _getAgentData(id) {
return this._agentData[id];
}
PhysicsEngine.prototype.getAgent = function getAgent(id) {
return _getAgentData.call(this, id).agent;
};
PhysicsEngine.prototype.getParticles = function getParticles() {
return this._particles;
};
PhysicsEngine.prototype.getBodies = function getBodies() {
return this._bodies;
};
PhysicsEngine.prototype.getParticlesAndBodies = function getParticlesAndBodies() {
return this.getParticles().concat(this.getBodies());
};
PhysicsEngine.prototype.forEachParticle = function forEachParticle(fn, dt) {
var particles = this.getParticles();
for (var index = 0, len = particles.length; index < len; index++)
fn.call(this, particles[index], dt);
};
PhysicsEngine.prototype.forEachBody = function forEachBody(fn, dt) {
if (!this._hasBodies)
return;
var bodies = this.getBodies();
for (var index = 0, len = bodies.length; index < len; index++)
fn.call(this, bodies[index], dt);
};
PhysicsEngine.prototype.forEach = function forEach(fn, dt) {
this.forEachParticle(fn, dt);
this.forEachBody(fn, dt);
};
function _updateForce(index) {
var boundAgent = _getAgentData.call(this, this._forces[index]);
boundAgent.agent.applyForce(boundAgent.targets, boundAgent.source);
}
function _updateForces() {
for (var index = this._forces.length - 1; index > -1; index--)
_updateForce.call(this, index);
}
function _updateConstraint(index, dt) {
var boundAgent = this._agentData[this._constraints[index]];
return boundAgent.agent.applyConstraint(boundAgent.targets, boundAgent.source, dt);
}
function _updateConstraints(dt) {
var iteration = 0;
while (iteration < this.options.constraintSteps) {
for (var index = this._constraints.length - 1; index > -1; index--)
_updateConstraint.call(this, index, dt);
iteration++;
}
}
function _updateVelocities(body, dt) {
body.integrateVelocity(dt);
if (this.options.velocityCap)
body.velocity.cap(this.options.velocityCap).put(body.velocity);
}
function _updateAngularVelocities(body, dt) {
body.integrateAngularMomentum(dt);
body.updateAngularVelocity();
if (this.options.angularVelocityCap)
body.angularVelocity.cap(this.options.angularVelocityCap).put(body.angularVelocity);
}
function _updateOrientations(body, dt) {
body.integrateOrientation(dt);
}
function _updatePositions(body, dt) {
body.integratePosition(dt);
body.emit(_events.update, body);
}
function _integrate(dt) {
_updateForces.call(this, dt);
this.forEach(_updateVelocities, dt);
this.forEachBody(_updateAngularVelocities, dt);
_updateConstraints.call(this, dt);
this.forEachBody(_updateOrientations, dt);
this.forEach(_updatePositions, dt);
}
function _getParticlesEnergy() {
var energy = 0;
var particleEnergy = 0;
this.forEach(function (particle) {
particleEnergy = particle.getEnergy();
energy += particleEnergy;
});
return energy;
}
function _getAgentsEnergy() {
var energy = 0;
for (var id in this._agentData)
energy += this.getAgentEnergy(id);
return energy;
}
PhysicsEngine.prototype.getAgentEnergy = function (agentId) {
var agentData = _getAgentData.call(this, agentId);
return agentData.agent.getEnergy(agentData.targets, agentData.source);
};
PhysicsEngine.prototype.getEnergy = function getEnergy() {
return _getParticlesEnergy.call(this) + _getAgentsEnergy.call(this);
};
PhysicsEngine.prototype.step = function step() {
if (this.isSleeping())
return;
var currTime = now();
var dtFrame = currTime - this._prevTime;
this._prevTime = currTime;
if (dtFrame < MIN_TIME_STEP)
return;
if (dtFrame > MAX_TIME_STEP)
dtFrame = MAX_TIME_STEP;
_integrate.call(this, TIMESTEP);
this.emit(_events.update, this);
if (this.getEnergy() < this.options.sleepTolerance)
this.sleep();
};
PhysicsEngine.prototype.isSleeping = function isSleeping() {
return this._isSleeping;
};
PhysicsEngine.prototype.isActive = function isSleeping() {
return !this._isSleeping;
};
PhysicsEngine.prototype.sleep = function sleep() {
if (this._isSleeping)
return;
this.forEach(function (body) {
body.sleep();
});
this.emit(_events.end, this);
this._isSleeping = true;
};
PhysicsEngine.prototype.wake = function wake() {
if (!this._isSleeping)
return;
this._prevTime = now();
this.emit(_events.start, this);
this._isSleeping = false;
};
PhysicsEngine.prototype.emit = function emit(type, data) {
if (this._eventHandler === null)
return;
this._eventHandler.emit(type, data);
};
PhysicsEngine.prototype.on = function on(event, fn) {
if (this._eventHandler === null)
this._eventHandler = new EventHandler();
this._eventHandler.on(event, fn);
};
module.exports = PhysicsEngine;
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var Vector = __webpack_require__(12);
var Transform = __webpack_require__(17);
var EventHandler = __webpack_require__(16);
var Integrator = __webpack_require__(18);
function Particle(options) {
options = options || {};
var defaults = Particle.DEFAULT_OPTIONS;
this.position = new Vector();
this.velocity = new Vector();
this.force = new Vector();
this._engine = null;
this._isSleeping = true;
this._eventOutput = null;
this.mass = options.mass !== undefined ? options.mass : defaults.mass;
this.inverseMass = 1 / this.mass;
this.setPosition(options.position || defaults.position);
this.setVelocity(options.velocity || defaults.velocity);
this.force.set(options.force || [
0,
0,
0
]);
this.transform = Transform.identity.slice();
this._spec = {
size: [
true,
true
],
target: {
transform: this.transform,
origin: [
0.5,
0.5
],
target: null
}
};
}
Particle.DEFAULT_OPTIONS = {
position: [
0,
0,
0
],
velocity: [
0,
0,
0
],
mass: 1
};
var _events = {
start: 'start',
update: 'update',
end: 'end'
};
var now = Date.now;
Particle.prototype.isBody = false;
Particle.prototype.isActive = function isActive() {
return !this._isSleeping;
};
Particle.prototype.sleep = function sleep() {
if (this._isSleeping)
return;
this.emit(_events.end, this);
this._isSleeping = true;
};
Particle.prototype.wake = function wake() {
if (!this._isSleeping)
return;
this.emit(_events.start, this);
this._isSleeping = false;
this._prevTime = now();
if (this._engine)
this._engine.wake();
};
Particle.prototype.setPosition = function setPosition(position) {
this.position.set(position);
};
Particle.prototype.setPosition1D = function setPosition1D(x) {
this.position.x = x;
};
Particle.prototype.getPosition = function getPosition() {
this._engine.step();
return this.position.get();
};
Particle.prototype.getPosition1D = function getPosition1D() {
this._engine.step();
return this.position.x;
};
Particle.prototype.setVelocity = function setVelocity(velocity) {
this.velocity.set(velocity);
if (!(velocity[0] === 0 && velocity[1] === 0 && velocity[2] === 0))
this.wake();
};
Particle.prototype.setVelocity1D = function setVelocity1D(x) {
this.velocity.x = x;
if (x !== 0)
this.wake();
};
Particle.prototype.getVelocity = function getVelocity() {
return this.velocity.get();
};
Particle.prototype.setForce = function setForce(force) {
this.force.set(force);
this.wake();
};
Particle.prototype.getVelocity1D = function getVelocity1D() {
return this.velocity.x;
};
Particle.prototype.setMass = function setMass(mass) {
this.mass = mass;
this.inverseMass = 1 / mass;
};
Particle.prototype.getMass = function getMass() {
return this.mass;
};
Particle.prototype.reset = function reset(position, velocity) {
this.setPosition(position || [
0,
0,
0
]);
this.setVelocity(velocity || [
0,
0,
0
]);
};
Particle.prototype.applyForce = function applyForce(force) {
if (force.isZero())
return;
this.force.add(force).put(this.force);
this.wake();
};
Particle.prototype.applyImpulse = function applyImpulse(impulse) {
if (impulse.isZero())
return;
var velocity = this.velocity;
velocity.add(impulse.mult(this.inverseMass)).put(velocity);
};
Particle.prototype.integrateVelocity = function integrateVelocity(dt) {
Integrator.integrateVelocity(this, dt);
};
Particle.prototype.integratePosition = function integratePosition(dt) {
Integrator.integratePosition(this, dt);
};
Particle.prototype._integrate = function _integrate(dt) {
this.integrateVelocity(dt);
this.integratePosition(dt);
};
Particle.prototype.getEnergy = function getEnergy() {
return 0.5 * this.mass * this.velocity.normSquared();
};
Particle.prototype.getTransform = function getTransform() {
this._engine.step();
var position = this.position;
var transform = this.transform;
transform[12] = position.x;
transform[13] = position.y;
transform[14] = position.z;
return transform;
};
Particle.prototype.modify = function modify(target) {
var _spec = this._spec.target;
_spec.transform = this.getTransform();
_spec.target = target;
return this._spec;
};
function _createEventOutput() {
this._eventOutput = new EventHandler();
this._eventOutput.bindThis(this);
EventHandler.setOutputHandler(this, this._eventOutput);
}
Particle.prototype.emit = function emit(type, data) {
if (!this._eventOutput)
return;
this._eventOutput.emit(type, data);
};
Particle.prototype.on = function on() {
_createEventOutput.call(this);
return this.on.apply(this, arguments);
};
Particle.prototype.removeListener = function removeListener() {
_createEventOutput.call(this);
return this.removeListener.apply(this, arguments);
};
Particle.prototype.pipe = function pipe() {
_createEventOutput.call(this);
return this.pipe.apply(this, arguments);
};
Particle.prototype.unpipe = function unpipe() {
_createEventOutput.call(this);
return this.unpipe.apply(this, arguments);
};
module.exports = Particle;
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can o