@popmotion/easing
Version:
Easing functions, modifiers and generators compatible with most animation libraries.
179 lines (175 loc) • 6.38 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var DEFAULT_OVERSHOOT_STRENGTH = 1.525;
var reversed = function (easing) { return function (p) { return 1 - easing(1 - p); }; };
var mirrored = function (easing) { return function (p) {
return p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
}; };
var createReversedEasing = reversed;
var createMirroredEasing = mirrored;
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 createAnticipateEasing = 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 linear = function (p) { return p; };
var easeIn = createExpoIn(2);
var easeOut = reversed(easeIn);
var easeInOut = mirrored(easeIn);
var circIn = function (p) { return 1 - Math.sin(Math.acos(p)); };
var circOut = reversed(circIn);
var circInOut = mirrored(circOut);
var backIn = createBackIn(DEFAULT_OVERSHOOT_STRENGTH);
var backOut = reversed(backIn);
var backInOut = mirrored(backIn);
var anticipate = createAnticipateEasing(DEFAULT_OVERSHOOT_STRENGTH);
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 ca = 4356.0 / 361.0;
var cb = 35442.0 / 1805.0;
var cc = 16061.0 / 1805.0;
var bounceOut = function (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 = function (p) { return 1.0 - bounceOut(1.0 - p); };
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;
};
var NEWTON_ITERATIONS = 8;
var NEWTON_MIN_SLOPE = 0.001;
var SUBDIVISION_PRECISION = 0.0000001;
var SUBDIVISION_MAX_ITERATIONS = 10;
var K_SPLINE_TABLE_SIZE = 11;
var K_SAMPLE_STEP_SIZE = 1.0 / (K_SPLINE_TABLE_SIZE - 1.0);
var FLOAT_32_SUPPORTED = typeof Float32Array !== 'undefined';
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 getSlope = function (t, a1, a2) {
return 3.0 * a(a1, a2) * t * t + 2.0 * b(a1, a2) * t + c(a1);
};
var calcBezier = function (t, a1, a2) {
return ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;
};
function cubicBezier(mX1, mY1, mX2, mY2) {
var sampleValues = FLOAT_32_SUPPORTED
? new Float32Array(K_SPLINE_TABLE_SIZE)
: new Array(K_SPLINE_TABLE_SIZE);
var binarySubdivide = function (aX, aA, aB) {
var i = 0;
var currentX;
var currentT;
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) > SUBDIVISION_PRECISION &&
++i < SUBDIVISION_MAX_ITERATIONS);
return currentT;
};
var newtonRaphsonIterate = function (aX, aGuessT) {
var i = 0;
var currentSlope = 0;
var currentX;
for (; i < NEWTON_ITERATIONS; ++i) {
currentSlope = getSlope(aGuessT, mX1, mX2);
if (currentSlope === 0.0) {
return aGuessT;
}
currentX = calcBezier(aGuessT, mX1, mX2) - aX;
aGuessT -= currentX / currentSlope;
}
return aGuessT;
};
var calcSampleValues = function () {
for (var i = 0; i < K_SPLINE_TABLE_SIZE; ++i) {
sampleValues[i] = calcBezier(i * K_SAMPLE_STEP_SIZE, mX1, mX2);
}
};
var getTForX = function (aX) {
var intervalStart = 0.0;
var currentSample = 1;
var lastSample = K_SPLINE_TABLE_SIZE - 1;
var dist = 0.0;
var guessForT = 0.0;
var initialSlope = 0.0;
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
intervalStart += K_SAMPLE_STEP_SIZE;
}
--currentSample;
dist =
(aX - sampleValues[currentSample]) /
(sampleValues[currentSample + 1] - sampleValues[currentSample]);
guessForT = intervalStart + dist * K_SAMPLE_STEP_SIZE;
initialSlope = getSlope(guessForT, mX1, mX2);
if (initialSlope >= NEWTON_MIN_SLOPE) {
return newtonRaphsonIterate(aX, guessForT);
}
else if (initialSlope === 0.0) {
return guessForT;
}
else {
return binarySubdivide(aX, intervalStart, intervalStart + K_SAMPLE_STEP_SIZE);
}
};
calcSampleValues();
var resolver = function (aX) {
var returnValue;
if (mX1 === mY1 && mX2 === mY2) {
returnValue = aX;
}
else if (aX === 0) {
returnValue = 0;
}
else if (aX === 1) {
returnValue = 1;
}
else {
returnValue = calcBezier(getTForX(aX), mY1, mY2);
}
return returnValue;
};
return resolver;
}
exports.reversed = reversed;
exports.mirrored = mirrored;
exports.createReversedEasing = createReversedEasing;
exports.createMirroredEasing = createMirroredEasing;
exports.createExpoIn = createExpoIn;
exports.createBackIn = createBackIn;
exports.createAnticipateEasing = createAnticipateEasing;
exports.linear = linear;
exports.easeIn = easeIn;
exports.easeOut = easeOut;
exports.easeInOut = easeInOut;
exports.circIn = circIn;
exports.circOut = circOut;
exports.circInOut = circInOut;
exports.backIn = backIn;
exports.backOut = backOut;
exports.backInOut = backInOut;
exports.anticipate = anticipate;
exports.bounceOut = bounceOut;
exports.bounceIn = bounceIn;
exports.bounceInOut = bounceInOut;
exports.cubicBezier = cubicBezier;