popmotion
Version:
The animator's toolbox
989 lines (947 loc) • 37.3 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var heyListen = require('hey-listen');
var styleValueTypes = require('style-value-types');
var sync = require('framesync');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var sync__default = /*#__PURE__*/_interopDefaultLegacy(sync);
var clamp = function (min, max, v) {
return Math.min(Math.max(v, min), max);
};
var safeMin = 0.001;
var minDuration = 0.01;
var maxDuration = 10.0;
var minDamping = 0.05;
var maxDamping = 1;
function findSpring(_a) {
var _b = _a.duration, duration = _b === void 0 ? 800 : _b, _c = _a.bounce, bounce = _c === void 0 ? 0.25 : _c, _d = _a.velocity, velocity = _d === void 0 ? 0 : _d, _e = _a.mass, mass = _e === void 0 ? 1 : _e;
var envelope;
var derivative;
heyListen.warning(duration <= maxDuration * 1000, "Spring duration must be 10 seconds or less");
var dampingRatio = 1 - bounce;
dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
duration = clamp(minDuration, maxDuration, duration / 1000);
if (dampingRatio < 1) {
envelope = function (undampedFreq) {
var exponentialDecay = undampedFreq * dampingRatio;
var delta = exponentialDecay * duration;
var a = exponentialDecay - velocity;
var b = calcAngularFreq(undampedFreq, dampingRatio);
var c = Math.exp(-delta);
return safeMin - (a / b) * c;
};
derivative = function (undampedFreq) {
var exponentialDecay = undampedFreq * dampingRatio;
var delta = exponentialDecay * duration;
var d = delta * velocity + velocity;
var e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration;
var f = Math.exp(-delta);
var g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio);
var factor = -envelope(undampedFreq) + safeMin > 0 ? -1 : 1;
return (factor * ((d - e) * f)) / g;
};
}
else {
envelope = function (undampedFreq) {
var a = Math.exp(-undampedFreq * duration);
var b = (undampedFreq - velocity) * duration + 1;
return -safeMin + a * b;
};
derivative = function (undampedFreq) {
var a = Math.exp(-undampedFreq * duration);
var b = (velocity - undampedFreq) * (duration * duration);
return a * b;
};
}
var initialGuess = 5 / duration;
var undampedFreq = approximateRoot(envelope, derivative, initialGuess);
if (isNaN(undampedFreq)) {
return {
stiffness: 100,
damping: 10,
};
}
else {
var stiffness = Math.pow(undampedFreq, 2) * mass;
return {
stiffness: stiffness,
damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
};
}
}
var rootIterations = 12;
function approximateRoot(envelope, derivative, initialGuess) {
var result = initialGuess;
for (var i = 1; i < rootIterations; i++) {
result = result - envelope(result) / derivative(result);
}
return result;
}
function calcAngularFreq(undampedFreq, dampingRatio) {
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
}
var durationKeys = ["duration", "bounce"];
var physicsKeys = ["stiffness", "damping", "mass"];
function isSpringType(options, keys) {
return keys.some(function (key) { return options[key] !== undefined; });
}
function getSpringOptions(options) {
var springOptions = tslib.__assign({ velocity: 0.0, stiffness: 100, damping: 10, mass: 1.0, isResolvedFromDuration: false }, options);
if (!isSpringType(options, physicsKeys) &&
isSpringType(options, durationKeys)) {
var derived = findSpring(options);
springOptions = tslib.__assign(tslib.__assign(tslib.__assign({}, springOptions), derived), { velocity: 0.0, mass: 1.0 });
springOptions.isResolvedFromDuration = true;
}
return springOptions;
}
function spring(_a) {
var _b = _a.from, from = _b === void 0 ? 0.0 : _b, _c = _a.to, to = _c === void 0 ? 1.0 : _c, _d = _a.restSpeed, restSpeed = _d === void 0 ? 2 : _d, restDelta = _a.restDelta, options = tslib.__rest(_a, ["from", "to", "restSpeed", "restDelta"]);
var state = { done: false, value: from };
var _e = getSpringOptions(options), stiffness = _e.stiffness, damping = _e.damping, mass = _e.mass, velocity = _e.velocity, isResolvedFromDuration = _e.isResolvedFromDuration;
var resolveSpring = zero;
var resolveVelocity = zero;
function createSpring() {
var initialVelocity = velocity ? -(velocity / 1000) : 0.0;
var initialDelta = to - from;
var dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
var undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
restDelta !== null && restDelta !== void 0 ? restDelta : (restDelta = Math.abs(to - from) <= 1 ? 0.01 : 0.4);
if (dampingRatio < 1) {
var angularFreq_1 = calcAngularFreq(undampedAngularFreq, dampingRatio);
resolveSpring = function (t) {
var envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
return (to -
envelope *
(((initialVelocity +
dampingRatio * undampedAngularFreq * initialDelta) /
angularFreq_1) *
Math.sin(angularFreq_1 * t) +
initialDelta * Math.cos(angularFreq_1 * t)));
};
resolveVelocity = function (t) {
var envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
return (dampingRatio *
undampedAngularFreq *
envelope *
((Math.sin(angularFreq_1 * t) *
(initialVelocity +
dampingRatio *
undampedAngularFreq *
initialDelta)) /
angularFreq_1 +
initialDelta * Math.cos(angularFreq_1 * t)) -
envelope *
(Math.cos(angularFreq_1 * t) *
(initialVelocity +
dampingRatio *
undampedAngularFreq *
initialDelta) -
angularFreq_1 *
initialDelta *
Math.sin(angularFreq_1 * t)));
};
}
else if (dampingRatio === 1) {
resolveSpring = function (t) {
return to -
Math.exp(-undampedAngularFreq * t) *
(initialDelta +
(initialVelocity + undampedAngularFreq * initialDelta) *
t);
};
}
else {
var dampedAngularFreq_1 = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
resolveSpring = function (t) {
var envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
var freqForT = Math.min(dampedAngularFreq_1 * t, 300);
return (to -
(envelope *
((initialVelocity +
dampingRatio * undampedAngularFreq * initialDelta) *
Math.sinh(freqForT) +
dampedAngularFreq_1 *
initialDelta *
Math.cosh(freqForT))) /
dampedAngularFreq_1);
};
}
}
createSpring();
return {
next: function (t) {
var current = resolveSpring(t);
if (!isResolvedFromDuration) {
var currentVelocity = resolveVelocity(t) * 1000;
var isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
var isBelowDisplacementThreshold = Math.abs(to - current) <= restDelta;
state.done =
isBelowVelocityThreshold && isBelowDisplacementThreshold;
}
else {
state.done = t >= options.duration;
}
state.value = state.done ? to : current;
return state;
},
flipTarget: function () {
var _a;
velocity = -velocity;
_a = [to, from], from = _a[0], to = _a[1];
createSpring();
},
};
}
spring.needsInterpolation = function (a, b) {
return typeof a === "string" || typeof b === "string";
};
var zero = function (_t) { return 0; };
var progress = function (from, to, value) {
var toFromDifference = to - from;
return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
};
var mix = function (from, to, progress) {
return -progress * from + progress * to + from;
};
var mixLinearColor = function (from, to, v) {
var fromExpo = from * from;
var toExpo = to * to;
return Math.sqrt(Math.max(0, v * (toExpo - fromExpo) + fromExpo));
};
var colorTypes = [styleValueTypes.hex, styleValueTypes.rgba, styleValueTypes.hsla];
var getColorType = function (v) {
return colorTypes.find(function (type) { return type.test(v); });
};
var notAnimatable = function (color) {
return "'" + color + "' is not an animatable color. Use the equivalent color code instead.";
};
var mixColor = function (from, to) {
var fromColorType = getColorType(from);
var toColorType = getColorType(to);
heyListen.invariant(!!fromColorType, notAnimatable(from));
heyListen.invariant(!!toColorType, notAnimatable(to));
heyListen.invariant(fromColorType.transform === toColorType.transform, "Both colors must be hex/RGBA, OR both must be HSLA.");
var fromColor = fromColorType.parse(from);
var toColor = toColorType.parse(to);
var blended = tslib.__assign({}, fromColor);
var mixFunc = fromColorType === styleValueTypes.hsla ? mix : mixLinearColor;
return function (v) {
for (var key in blended) {
if (key !== "alpha") {
blended[key] = mixFunc(fromColor[key], toColor[key], v);
}
}
blended.alpha = mix(fromColor.alpha, toColor.alpha, v);
return fromColorType.transform(blended);
};
};
var zeroPoint = {
x: 0,
y: 0,
z: 0
};
var isNum = function (v) { return typeof v === 'number'; };
var combineFunctions = function (a, b) { return function (v) { return b(a(v)); }; };
var pipe = function () {
var transformers = [];
for (var _i = 0; _i < arguments.length; _i++) {
transformers[_i] = arguments[_i];
}
return transformers.reduce(combineFunctions);
};
function getMixer(origin, target) {
if (isNum(origin)) {
return function (v) { return mix(origin, target, v); };
}
else if (styleValueTypes.color.test(origin)) {
return mixColor(origin, target);
}
else {
return mixComplex(origin, target);
}
}
var mixArray = function (from, to) {
var output = tslib.__spreadArrays(from);
var numValues = output.length;
var blendValue = from.map(function (fromThis, i) { return getMixer(fromThis, to[i]); });
return function (v) {
for (var i = 0; i < numValues; i++) {
output[i] = blendValue[i](v);
}
return output;
};
};
var mixObject = function (origin, target) {
var output = tslib.__assign(tslib.__assign({}, origin), target);
var blendValue = {};
for (var key in output) {
if (origin[key] !== undefined && target[key] !== undefined) {
blendValue[key] = getMixer(origin[key], target[key]);
}
}
return function (v) {
for (var key in blendValue) {
output[key] = blendValue[key](v);
}
return output;
};
};
function analyse(value) {
var parsed = styleValueTypes.complex.parse(value);
var numValues = parsed.length;
var numNumbers = 0;
var numRGB = 0;
var numHSL = 0;
for (var i = 0; i < numValues; i++) {
if (numNumbers || typeof parsed[i] === "number") {
numNumbers++;
}
else {
if (parsed[i].hue !== undefined) {
numHSL++;
}
else {
numRGB++;
}
}
}
return { parsed: parsed, numNumbers: numNumbers, numRGB: numRGB, numHSL: numHSL };
}
var mixComplex = function (origin, target) {
var template = styleValueTypes.complex.createTransformer(target);
var originStats = analyse(origin);
var targetStats = analyse(target);
heyListen.invariant(originStats.numHSL === targetStats.numHSL &&
originStats.numRGB === targetStats.numRGB &&
originStats.numNumbers >= targetStats.numNumbers, "Complex values '" + origin + "' and '" + target + "' too different to mix. Ensure all colors are of the same type.");
return pipe(mixArray(originStats.parsed, targetStats.parsed), template);
};
var mixNumber = function (from, to) { return function (p) { return mix(from, to, p); }; };
function detectMixerFactory(v) {
if (typeof v === 'number') {
return mixNumber;
}
else if (typeof v === 'string') {
if (styleValueTypes.color.test(v)) {
return mixColor;
}
else {
return mixComplex;
}
}
else if (Array.isArray(v)) {
return mixArray;
}
else if (typeof v === 'object') {
return mixObject;
}
}
function createMixers(output, ease, customMixer) {
var mixers = [];
var mixerFactory = customMixer || detectMixerFactory(output[0]);
var numMixers = output.length - 1;
for (var i = 0; i < numMixers; i++) {
var mixer = mixerFactory(output[i], output[i + 1]);
if (ease) {
var easingFunction = Array.isArray(ease) ? ease[i] : ease;
mixer = pipe(easingFunction, mixer);
}
mixers.push(mixer);
}
return mixers;
}
function fastInterpolate(_a, _b) {
var from = _a[0], to = _a[1];
var mixer = _b[0];
return function (v) { return mixer(progress(from, to, v)); };
}
function slowInterpolate(input, mixers) {
var inputLength = input.length;
var lastInputIndex = inputLength - 1;
return function (v) {
var mixerIndex = 0;
var foundMixerIndex = false;
if (v <= input[0]) {
foundMixerIndex = true;
}
else if (v >= input[lastInputIndex]) {
mixerIndex = lastInputIndex - 1;
foundMixerIndex = true;
}
if (!foundMixerIndex) {
var i = 1;
for (; i < inputLength; i++) {
if (input[i] > v || i === lastInputIndex) {
break;
}
}
mixerIndex = i - 1;
}
var progressInRange = progress(input[mixerIndex], input[mixerIndex + 1], v);
return mixers[mixerIndex](progressInRange);
};
}
function interpolate(input, output, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.clamp, isClamp = _c === void 0 ? true : _c, ease = _b.ease, mixer = _b.mixer;
var inputLength = input.length;
heyListen.invariant(inputLength === output.length, 'Both input and output ranges must be the same length');
heyListen.invariant(!ease || !Array.isArray(ease) || ease.length === inputLength - 1, 'Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.');
if (input[0] > input[inputLength - 1]) {
input = [].concat(input);
output = [].concat(output);
input.reverse();
output.reverse();
}
var mixers = createMixers(output, ease, mixer);
var interpolator = inputLength === 2
? fastInterpolate(input, mixers)
: slowInterpolate(input, mixers);
return isClamp
? function (v) { return interpolator(clamp(input[0], input[inputLength - 1], v)); }
: interpolator;
}
var reverseEasing = function (easing) { return function (p) { return 1 - easing(1 - p); }; };
var mirrorEasing = function (easing) { return function (p) {
return p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
}; };
var createExpoIn = function (power) { return function (p) { return Math.pow(p, power); }; };
var createBackIn = function (power) { return function (p) {
return p * p * ((power + 1) * p - power);
}; };
var createAnticipate = function (power) {
var backEasing = createBackIn(power);
return function (p) {
return (p *= 2) < 1
? 0.5 * backEasing(p)
: 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
};
};
var DEFAULT_OVERSHOOT_STRENGTH = 1.525;
var BOUNCE_FIRST_THRESHOLD = 4.0 / 11.0;
var BOUNCE_SECOND_THRESHOLD = 8.0 / 11.0;
var BOUNCE_THIRD_THRESHOLD = 9.0 / 10.0;
var linear = function (p) { return p; };
var easeIn = createExpoIn(2);
var easeOut = reverseEasing(easeIn);
var easeInOut = mirrorEasing(easeIn);
var circIn = function (p) { return 1 - Math.sin(Math.acos(p)); };
var circOut = reverseEasing(circIn);
var circInOut = mirrorEasing(circOut);
var backIn = createBackIn(DEFAULT_OVERSHOOT_STRENGTH);
var backOut = reverseEasing(backIn);
var backInOut = mirrorEasing(backIn);
var anticipate = createAnticipate(DEFAULT_OVERSHOOT_STRENGTH);
var ca = 4356.0 / 361.0;
var cb = 35442.0 / 1805.0;
var cc = 16061.0 / 1805.0;
var bounceOut = function (p) {
if (p === 1 || p === 0)
return p;
var p2 = p * p;
return p < BOUNCE_FIRST_THRESHOLD
? 7.5625 * p2
: p < BOUNCE_SECOND_THRESHOLD
? 9.075 * p2 - 9.9 * p + 3.4
: p < BOUNCE_THIRD_THRESHOLD
? ca * p2 - cb * p + cc
: 10.8 * p * p - 20.52 * p + 10.72;
};
var bounceIn = reverseEasing(bounceOut);
var bounceInOut = function (p) {
return p < 0.5
? 0.5 * (1.0 - bounceOut(1.0 - p * 2.0))
: 0.5 * bounceOut(p * 2.0 - 1.0) + 0.5;
};
function defaultEasing(values, easing) {
return values.map(function () { return easing || easeInOut; }).splice(0, values.length - 1);
}
function defaultOffset(values) {
var numValues = values.length;
return values.map(function (_value, i) {
return i !== 0 ? i / (numValues - 1) : 0;
});
}
function convertOffsetToTimes(offset, duration) {
return offset.map(function (o) { return o * duration; });
}
function keyframes(_a) {
var _b = _a.from, from = _b === void 0 ? 0 : _b, _c = _a.to, to = _c === void 0 ? 1 : _c, ease = _a.ease, offset = _a.offset, _d = _a.duration, duration = _d === void 0 ? 300 : _d;
var state = { done: false, value: from };
var values = Array.isArray(to) ? to : [from, to];
var times = convertOffsetToTimes(offset && offset.length === values.length
? offset
: defaultOffset(values), duration);
function createInterpolator() {
return interpolate(times, values, {
ease: Array.isArray(ease) ? ease : defaultEasing(values, ease),
});
}
var interpolator = createInterpolator();
return {
next: function (t) {
state.value = interpolator(t);
state.done = t >= duration;
return state;
},
flipTarget: function () {
values.reverse();
interpolator = createInterpolator();
},
};
}
function decay(_a) {
var _b = _a.velocity, velocity = _b === void 0 ? 0 : _b, _c = _a.from, from = _c === void 0 ? 0 : _c, _d = _a.power, power = _d === void 0 ? 0.8 : _d, _e = _a.timeConstant, timeConstant = _e === void 0 ? 350 : _e, _f = _a.restDelta, restDelta = _f === void 0 ? 0.5 : _f, modifyTarget = _a.modifyTarget;
var state = { done: false, value: from };
var amplitude = power * velocity;
var ideal = from + amplitude;
var target = modifyTarget === undefined ? ideal : modifyTarget(ideal);
if (target !== ideal)
amplitude = target - from;
return {
next: function (t) {
var delta = -amplitude * Math.exp(-t / timeConstant);
state.done = !(delta > restDelta || delta < -restDelta);
state.value = state.done ? target : target + delta;
return state;
},
flipTarget: function () { },
};
}
var types = { keyframes: keyframes, spring: spring, decay: decay };
function detectAnimationFromOptions(config) {
if (Array.isArray(config.to)) {
return keyframes;
}
else if (types[config.type]) {
return types[config.type];
}
var keys = new Set(Object.keys(config));
if (keys.has("ease") ||
(keys.has("duration") && !keys.has("dampingRatio"))) {
return keyframes;
}
else if (keys.has("dampingRatio") ||
keys.has("stiffness") ||
keys.has("mass") ||
keys.has("damping") ||
keys.has("restSpeed") ||
keys.has("restDelta")) {
return spring;
}
return keyframes;
}
function loopElapsed(elapsed, duration, delay) {
if (delay === void 0) { delay = 0; }
return elapsed - duration - delay;
}
function reverseElapsed(elapsed, duration, delay, isForwardPlayback) {
if (delay === void 0) { delay = 0; }
if (isForwardPlayback === void 0) { isForwardPlayback = true; }
return isForwardPlayback
? loopElapsed(duration + -elapsed, duration, delay)
: duration - (elapsed - duration) + delay;
}
function hasRepeatDelayElapsed(elapsed, duration, delay, isForwardPlayback) {
return isForwardPlayback ? elapsed >= duration + delay : elapsed <= -delay;
}
var framesync = function (update) {
var passTimestamp = function (_a) {
var delta = _a.delta;
return update(delta);
};
return {
start: function () { return sync__default['default'].update(passTimestamp, true); },
stop: function () { return sync.cancelSync.update(passTimestamp); },
};
};
function animate(_a) {
var _b, _c;
var from = _a.from, _d = _a.autoplay, autoplay = _d === void 0 ? true : _d, _e = _a.driver, driver = _e === void 0 ? framesync : _e, _f = _a.elapsed, elapsed = _f === void 0 ? 0 : _f, _g = _a.repeat, repeatMax = _g === void 0 ? 0 : _g, _h = _a.repeatType, repeatType = _h === void 0 ? "loop" : _h, _j = _a.repeatDelay, repeatDelay = _j === void 0 ? 0 : _j, onPlay = _a.onPlay, onStop = _a.onStop, onComplete = _a.onComplete, onRepeat = _a.onRepeat, onUpdate = _a.onUpdate, options = tslib.__rest(_a, ["from", "autoplay", "driver", "elapsed", "repeat", "repeatType", "repeatDelay", "onPlay", "onStop", "onComplete", "onRepeat", "onUpdate"]);
var to = options.to;
var driverControls;
var repeatCount = 0;
var computedDuration = options.duration;
var latest;
var isComplete = false;
var isForwardPlayback = true;
var interpolateFromNumber;
var animator = detectAnimationFromOptions(options);
if ((_c = (_b = animator).needsInterpolation) === null || _c === void 0 ? void 0 : _c.call(_b, from, to)) {
interpolateFromNumber = interpolate([0, 100], [from, to], {
clamp: false,
});
from = 0;
to = 100;
}
var animation = animator(tslib.__assign(tslib.__assign({}, options), { from: from, to: to }));
function repeat() {
repeatCount++;
if (repeatType === "reverse") {
isForwardPlayback = repeatCount % 2 === 0;
elapsed = reverseElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback);
}
else {
elapsed = loopElapsed(elapsed, computedDuration, repeatDelay);
if (repeatType === "mirror")
animation.flipTarget();
}
isComplete = false;
onRepeat && onRepeat();
}
function complete() {
driverControls.stop();
onComplete && onComplete();
}
function update(delta) {
if (!isForwardPlayback)
delta = -delta;
elapsed += delta;
if (!isComplete) {
var state = animation.next(Math.max(0, elapsed));
latest = state.value;
if (interpolateFromNumber)
latest = interpolateFromNumber(latest);
isComplete = isForwardPlayback ? state.done : elapsed <= 0;
}
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(latest);
if (isComplete) {
if (repeatCount === 0)
computedDuration !== null && computedDuration !== void 0 ? computedDuration : (computedDuration = elapsed);
if (repeatCount < repeatMax) {
hasRepeatDelayElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback) && repeat();
}
else {
complete();
}
}
}
function play() {
onPlay === null || onPlay === void 0 ? void 0 : onPlay();
driverControls = driver(update);
driverControls.start();
}
autoplay && play();
return {
stop: function () {
onStop === null || onStop === void 0 ? void 0 : onStop();
driverControls.stop();
},
};
}
function velocityPerSecond(velocity, frameDuration) {
return frameDuration ? velocity * (1000 / frameDuration) : 0;
}
function inertia(_a) {
var _b = _a.from, from = _b === void 0 ? 0 : _b, _c = _a.velocity, velocity = _c === void 0 ? 0 : _c, min = _a.min, max = _a.max, _d = _a.power, power = _d === void 0 ? 0.8 : _d, _e = _a.timeConstant, timeConstant = _e === void 0 ? 750 : _e, _f = _a.bounceStiffness, bounceStiffness = _f === void 0 ? 500 : _f, _g = _a.bounceDamping, bounceDamping = _g === void 0 ? 10 : _g, _h = _a.restDelta, restDelta = _h === void 0 ? 1 : _h, modifyTarget = _a.modifyTarget, driver = _a.driver, onUpdate = _a.onUpdate, onComplete = _a.onComplete;
var currentAnimation;
function isOutOfBounds(v) {
return (min !== undefined && v < min) || (max !== undefined && v > max);
}
function boundaryNearest(v) {
if (min === undefined)
return max;
if (max === undefined)
return min;
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
}
function startAnimation(options) {
currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop();
currentAnimation = animate(tslib.__assign(tslib.__assign({}, options), { driver: driver, onUpdate: function (v) {
var _a;
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(v);
(_a = options.onUpdate) === null || _a === void 0 ? void 0 : _a.call(options, v);
}, onComplete: onComplete }));
}
function startSpring(options) {
startAnimation(tslib.__assign({ type: "spring", stiffness: bounceStiffness, damping: bounceDamping, restDelta: restDelta }, options));
}
if (isOutOfBounds(from)) {
startSpring({ from: from, velocity: velocity, to: boundaryNearest(from) });
}
else {
var target = power * velocity + from;
if (typeof modifyTarget !== "undefined")
target = modifyTarget(target);
var boundary_1 = boundaryNearest(target);
var heading_1 = boundary_1 === min ? -1 : 1;
var prev_1;
var current_1;
var checkBoundary = function (v) {
prev_1 = current_1;
current_1 = v;
velocity = velocityPerSecond(v - prev_1, sync.getFrameData().delta);
if ((heading_1 === 1 && v > boundary_1) ||
(heading_1 === -1 && v < boundary_1)) {
startSpring({ from: v, to: boundary_1, velocity: velocity });
}
};
startAnimation({
type: "decay",
from: from,
velocity: velocity,
timeConstant: timeConstant,
power: power,
restDelta: restDelta,
modifyTarget: modifyTarget,
onUpdate: isOutOfBounds(target) ? checkBoundary : undefined,
});
}
return {
stop: function () { return currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop(); },
};
}
var radiansToDegrees = function (radians) { return (radians * 180) / Math.PI; };
var angle = function (a, b) {
if (b === void 0) { b = zeroPoint; }
return radiansToDegrees(Math.atan2(b.y - a.y, b.x - a.x));
};
var applyOffset = function (from, to) {
var hasReceivedFrom = true;
if (to === undefined) {
to = from;
hasReceivedFrom = false;
}
return function (v) {
if (hasReceivedFrom) {
return v - from + to;
}
else {
from = v;
hasReceivedFrom = true;
return to;
}
};
};
var identity = function (v) { return v; };
var createAttractor = function (alterDisplacement) {
if (alterDisplacement === void 0) { alterDisplacement = identity; }
return function (constant, origin, v) {
var displacement = origin - v;
var springModifiedDisplacement = -(0 - constant + 1) * (0 - alterDisplacement(Math.abs(displacement)));
return displacement <= 0
? origin + springModifiedDisplacement
: origin - springModifiedDisplacement;
};
};
var attract = createAttractor();
var attractExpo = createAttractor(Math.sqrt);
var degreesToRadians = function (degrees) { return (degrees * Math.PI) / 180; };
var isPoint = function (point) {
return point.hasOwnProperty('x') && point.hasOwnProperty('y');
};
var isPoint3D = function (point) {
return isPoint(point) && point.hasOwnProperty('z');
};
var distance1D = function (a, b) { return Math.abs(a - b); };
function distance(a, b) {
if (isNum(a) && isNum(b)) {
return distance1D(a, b);
}
else if (isPoint(a) && isPoint(b)) {
var xDelta = distance1D(a.x, b.x);
var yDelta = distance1D(a.y, b.y);
var zDelta = isPoint3D(a) && isPoint3D(b) ? distance1D(a.z, b.z) : 0;
return Math.sqrt(Math.pow(xDelta, 2) + Math.pow(yDelta, 2) + Math.pow(zDelta, 2));
}
}
var pointFromVector = function (origin, angle, distance) {
angle = degreesToRadians(angle);
return {
x: distance * Math.cos(angle) + origin.x,
y: distance * Math.sin(angle) + origin.y
};
};
var toDecimal = function (num, precision) {
if (precision === void 0) { precision = 2; }
precision = Math.pow(10, precision);
return Math.round(num * precision) / precision;
};
var smoothFrame = function (prevValue, nextValue, duration, smoothing) {
if (smoothing === void 0) { smoothing = 0; }
return toDecimal(prevValue +
(duration * (nextValue - prevValue)) / Math.max(smoothing, duration));
};
var smooth = function (strength) {
if (strength === void 0) { strength = 50; }
var previousValue = 0;
var lastUpdated = 0;
return function (v) {
var currentFramestamp = sync.getFrameData().timestamp;
var timeDelta = currentFramestamp !== lastUpdated ? currentFramestamp - lastUpdated : 0;
var newValue = timeDelta
? smoothFrame(previousValue, v, timeDelta, strength)
: previousValue;
lastUpdated = currentFramestamp;
previousValue = newValue;
return newValue;
};
};
var snap = function (points) {
if (typeof points === 'number') {
return function (v) { return Math.round(v / points) * points; };
}
else {
var i_1 = 0;
var numPoints_1 = points.length;
return function (v) {
var lastDistance = Math.abs(points[0] - v);
for (i_1 = 1; i_1 < numPoints_1; i_1++) {
var point = points[i_1];
var distance = Math.abs(point - v);
if (distance === 0)
return point;
if (distance > lastDistance)
return points[i_1 - 1];
if (i_1 === numPoints_1 - 1)
return point;
lastDistance = distance;
}
};
}
};
function velocityPerFrame(xps, frameDuration) {
return xps / (1000 / frameDuration);
}
var wrap = function (min, max, v) {
var rangeSize = max - min;
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
};
var a = function (a1, a2) { return 1.0 - 3.0 * a2 + 3.0 * a1; };
var b = function (a1, a2) { return 3.0 * a2 - 6.0 * a1; };
var c = function (a1) { return 3.0 * a1; };
var calcBezier = function (t, a1, a2) {
return ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;
};
var getSlope = function (t, a1, a2) {
return 3.0 * a(a1, a2) * t * t + 2.0 * b(a1, a2) * t + c(a1);
};
var subdivisionPrecision = 0.0000001;
var subdivisionMaxIterations = 10;
function binarySubdivide(aX, aA, aB, mX1, mX2) {
var currentX;
var currentT;
var i = 0;
do {
currentT = aA + (aB - aA) / 2.0;
currentX = calcBezier(currentT, mX1, mX2) - aX;
if (currentX > 0.0) {
aB = currentT;
}
else {
aA = currentT;
}
} while (Math.abs(currentX) > subdivisionPrecision &&
++i < subdivisionMaxIterations);
return currentT;
}
var newtonIterations = 8;
var newtonMinSlope = 0.001;
function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
for (var i = 0; i < newtonIterations; ++i) {
var currentSlope = getSlope(aGuessT, mX1, mX2);
if (currentSlope === 0.0) {
return aGuessT;
}
var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
aGuessT -= currentX / currentSlope;
}
return aGuessT;
}
var kSplineTableSize = 11;
var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
function cubicBezier(mX1, mY1, mX2, mY2) {
if (mX1 === mY1 && mX2 === mY2)
return linear;
var sampleValues = new Float32Array(kSplineTableSize);
for (var i = 0; i < kSplineTableSize; ++i) {
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
}
function getTForX(aX) {
var intervalStart = 0.0;
var currentSample = 1;
var lastSample = kSplineTableSize - 1;
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
intervalStart += kSampleStepSize;
}
--currentSample;
var dist = (aX - sampleValues[currentSample]) /
(sampleValues[currentSample + 1] - sampleValues[currentSample]);
var guessForT = intervalStart + dist * kSampleStepSize;
var initialSlope = getSlope(guessForT, mX1, mX2);
if (initialSlope >= newtonMinSlope) {
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
}
else if (initialSlope === 0.0) {
return guessForT;
}
else {
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
}
}
return function (t) {
return t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
};
}
var steps = function (steps, direction) {
if (direction === void 0) { direction = 'end'; }
return function (progress) {
progress =
direction === 'end' ? Math.min(progress, 0.999) : Math.max(progress, 0.001);
var expanded = progress * steps;
var rounded = direction === 'end' ? Math.floor(expanded) : Math.ceil(expanded);
return clamp(0, 1, rounded / steps);
};
};
exports.angle = angle;
exports.animate = animate;
exports.anticipate = anticipate;
exports.applyOffset = applyOffset;
exports.attract = attract;
exports.attractExpo = attractExpo;
exports.backIn = backIn;
exports.backInOut = backInOut;
exports.backOut = backOut;
exports.bounceIn = bounceIn;
exports.bounceInOut = bounceInOut;
exports.bounceOut = bounceOut;
exports.circIn = circIn;
exports.circInOut = circInOut;
exports.circOut = circOut;
exports.clamp = clamp;
exports.createAnticipate = createAnticipate;
exports.createAttractor = createAttractor;
exports.createBackIn = createBackIn;
exports.createExpoIn = createExpoIn;
exports.cubicBezier = cubicBezier;
exports.decay = decay;
exports.degreesToRadians = degreesToRadians;
exports.distance = distance;
exports.easeIn = easeIn;
exports.easeInOut = easeInOut;
exports.easeOut = easeOut;
exports.inertia = inertia;
exports.interpolate = interpolate;
exports.isPoint = isPoint;
exports.isPoint3D = isPoint3D;
exports.keyframes = keyframes;
exports.linear = linear;
exports.mirrorEasing = mirrorEasing;
exports.mix = mix;
exports.mixColor = mixColor;
exports.mixComplex = mixComplex;
exports.pipe = pipe;
exports.pointFromVector = pointFromVector;
exports.progress = progress;
exports.radiansToDegrees = radiansToDegrees;
exports.reverseEasing = reverseEasing;
exports.smooth = smooth;
exports.smoothFrame = smoothFrame;
exports.snap = snap;
exports.spring = spring;
exports.steps = steps;
exports.toDecimal = toDecimal;
exports.velocityPerFrame = velocityPerFrame;
exports.velocityPerSecond = velocityPerSecond;
exports.wrap = wrap;
;