UNPKG

addimated

Version:

An always interruptable, declarative animation library for React

219 lines (179 loc) 9.08 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.SpringAnimation = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _invariant = _interopRequireDefault(require("invariant")); var _Animation2 = require("./Animation"); var _SpringConfig = require("./SpringConfig"); var _WithDefault = require("./WithDefault"); var SpringAnimation = /*#__PURE__*/ function (_Animation) { (0, _inherits2.default)(SpringAnimation, _Animation); function SpringAnimation(config) { var _this; (0, _classCallCheck2.default)(this, SpringAnimation); _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpringAnimation).call(this)); _this.overshootClamping = (0, _WithDefault.withDefault)(config.overshootClamping, false); _this.restDisplacementThreshold = (0, _WithDefault.withDefault)(config.restDisplacementThreshold, 0.001); _this.restSpeedThreshold = (0, _WithDefault.withDefault)(config.restSpeedThreshold, 0.001); _this.initialVelocity = (0, _WithDefault.withDefault)(config.velocity, NaN); _this.lastVelocity = (0, _WithDefault.withDefault)(config.velocity, NaN); _this.toValue = config.toValue; _this.delay = (0, _WithDefault.withDefault)(config.delay, 0); if (config.stiffness !== undefined || config.damping !== undefined || config.mass !== undefined) { !(config.bounciness === undefined && config.speed === undefined && config.tension === undefined && config.friction === undefined) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one") : invariant(false) : void 0; _this.stiffness = (0, _WithDefault.withDefault)(config.stiffness, 100); _this.damping = (0, _WithDefault.withDefault)(config.damping, 10); _this.mass = (0, _WithDefault.withDefault)(config.mass, 1); } else if (config.bounciness !== undefined || config.speed !== undefined) { // Convert the origami bounciness/speed values to stiffness/damping // We assume mass is 1. !(config.tension === undefined && config.friction === undefined && config.stiffness === undefined && config.damping === undefined && config.mass === undefined) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one") : invariant(false) : void 0; var springConfig = (0, _SpringConfig.fromBouncinessAndSpeed)((0, _WithDefault.withDefault)(config.bounciness, 8), (0, _WithDefault.withDefault)(config.speed, 12)); _this.stiffness = springConfig.stiffness; _this.damping = springConfig.damping; _this.mass = 1; } else { // Convert the origami tension/friction values to stiffness/damping // We assume mass is 1. var _springConfig = (0, _SpringConfig.fromOrigamiTensionAndFriction)((0, _WithDefault.withDefault)(config.tension, 40), (0, _WithDefault.withDefault)(config.friction, 7)); _this.stiffness = _springConfig.stiffness; _this.damping = _springConfig.damping; _this.mass = 1; } !(_this.stiffness > 0) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "Stiffness value must be greater than 0") : invariant(false) : void 0; !(_this.damping > 0) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "Damping value must be greater than 0") : invariant(false) : void 0; !(_this.mass > 0) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "Mass value must be greater than 0") : invariant(false) : void 0; return _this; } (0, _createClass2.default)(SpringAnimation, [{ key: "getInternalState", value: function getInternalState() { return { lastPosition: this.lastPosition, lastVelocity: this.lastVelocity, lastTime: this.lastTime }; } }, { key: "nextFrame", value: function nextFrame(now) { // TODO: Rethink delay handling here if (now <= this.lastTime) return [this.startPosition, false]; var deltaTime = (now - this.lastTime) / 1000; this.frameTime += deltaTime; var c = this.damping; var m = this.mass; var k = this.stiffness; var v0 = -this.initialVelocity; var zeta = c / (2 * Math.sqrt(k * m)); // damping ratio var omega0 = Math.sqrt(k / m); // undamped angular frequency of the oscillator (rad/ms) var omega1 = omega0 * Math.sqrt(1.0 - zeta * zeta); // exponential decay var x0 = this.toValue - this.startPosition; // calculate the oscillation from x0 = 1 to x = 0 var position = 0.0; var velocity = 0.0; var t = this.frameTime; if (zeta < 1) { // Under damped var envelope = Math.exp(-zeta * omega0 * t); position = this.toValue - envelope * ((v0 + zeta * omega0 * x0) / omega1 * Math.sin(omega1 * t) + x0 * Math.cos(omega1 * t)); // This looks crazy -- it's actually just the derivative of the // oscillation function velocity = zeta * omega0 * envelope * (Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0) / omega1 + x0 * Math.cos(omega1 * t)) - envelope * (Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0) - omega1 * x0 * Math.sin(omega1 * t)); } else { // Critically damped var _envelope = Math.exp(-omega0 * t); position = this.toValue - _envelope * (x0 + (v0 + omega0 * x0) * t); velocity = _envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0)); } this.lastTime = now; this.lastPosition = position; this.lastVelocity = velocity; // Conditions for stopping the spring animation var finished = false; var isOvershooting = false; if (this.overshootClamping && this.stiffness !== 0) { if (this.startPosition < this.toValue) { isOvershooting = position > this.toValue; } else { isOvershooting = position < this.toValue; } } var isVelocity = Math.abs(velocity) <= this.restSpeedThreshold; var isDisplacement = true; if (this.stiffness !== 0) { isDisplacement = Math.abs(this.toValue - position) <= this.restDisplacementThreshold; } if (isOvershooting || isVelocity && isDisplacement) { if (this.stiffness !== 0) { // Ensure that we end up with a round value this.lastPosition = this.toValue; this.lastVelocity = 0; position = this.toValue; } finished = true; } return [position, finished]; } }, { key: "start", value: function start(animatedVal, _fromValue, onEnd) { var currentVal = animatedVal.__getValue(); animatedVal.model = this.toValue; this.active = true; this.fromValue = currentVal - this.toValue; this.toValue = 0; this.endCallback = onEnd; if (isNaN(this.initialVelocity) || isNaN(this.lastVelocity)) { var velocity = animatedVal.velocity != null ? animatedVal.velocity * 1000 : 0; this.initialVelocity = velocity; this.lastVelocity = velocity; } this.startPosition = this.fromValue; this.lastPosition = this.startPosition; this.currentValue = currentVal; this.lastTime = performance.now() + this.delay; this.frameTime = 0; animatedVal.animations.forEach(function (anim) { return anim.stop(false); }); return [this]; } }, { key: "step", value: function step(timestamp) { var _this$nextFrame = this.nextFrame(timestamp), _this$nextFrame2 = (0, _slicedToArray2.default)(_this$nextFrame, 2), currentValue = _this$nextFrame2[0], finished = _this$nextFrame2[1]; this.currentValue = currentValue; if (finished) { this.stop(true); } } }, { key: "getValue", value: function getValue() { return this.currentValue; } }, { key: "stop", value: function stop() { var finished = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; this.ended = true; this.endCallback && this.endCallback({ finished: finished }); } }]); return SpringAnimation; }(_Animation2.Animation); exports.SpringAnimation = SpringAnimation; //# sourceMappingURL=SpringAnimation.js.map