[RN] improve elastic easing

Summary:
1) Makes params more intuitive (only one now, bounciness, which maps intuitively to number of oscillations).
2) Satisfies boundary conditions (f(0) = 0, f(1) = 1) so animation actually goes where you tell it (before it would finish at a random location depending on the input params).
3) Simple test to verify boundary conditions.
This commit is contained in:
Spencer Ahrens 2015-08-31 13:50:24 -07:00
parent d87480e9ac
commit 9ad2c322c0
2 changed files with 23 additions and 14 deletions

View File

@ -59,21 +59,22 @@ class Easing {
return Math.pow(2, 10 * (t - 1)); return Math.pow(2, 10 * (t - 1));
} }
static elastic(a: number, p: number): (t: number) => number { /**
var tau = Math.PI * 2; * A simple elastic interaction, similar to a spring. Default bounciness
// flow isn't smart enough to figure out that s is always assigned to a * is 1, which overshoots a little bit once. 0 bounciness doesn't overshoot
// number before being used in the returned function * at all, and bounciness of N > 1 will overshoot about N times.
var s: any; *
if (arguments.length < 2) { * Wolfram Plots:
p = 0.45; *
* http://tiny.cc/elastic_b_1 (default bounciness = 1)
* http://tiny.cc/elastic_b_3 (bounciness = 3)
*/
static elastic(bounciness: number): (t: number) => number {
if (arguments.length === 0) {
bounciness = 1;
} }
if (arguments.length) { var p = bounciness * Math.PI;
s = p / tau * Math.asin(1 / a); return (t) => 1 - Math.pow(Math.cos(t * Math.PI / 2), 3) * Math.cos(t * p);
} else {
a = 1;
s = p / 4;
}
return (t) => 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * tau / p);
}; };
static back(s: number): (t: number) => number { static back(s: number): (t: number) => number {

View File

@ -71,6 +71,14 @@ describe('Easing', () => {
} }
}); });
it('should satisfy boundary conditions with elastic', () => {
for (var b = 0; b < 4; b += 0.3) {
var easing = Easing.elastic(b);
expect(easing(0)).toBe(0);
expect(easing(1)).toBe(1);
}
});
function sampleEasingFunction(easing) { function sampleEasingFunction(easing) {
var DURATION = 300; var DURATION = 300;
var tickCount = Math.round(DURATION * 60 / 1000); var tickCount = Math.round(DURATION * 60 / 1000);