Commit 57318fa3 authored by Marco Scannadinari's avatar Marco Scannadinari Committed by Dan Field

Add Robert Penner’s easing functions (#25788)

* Add Robert Penner’s easing functions

These easing functions are the most popular functions in use on the web
and other platforms. Including them in Flutter will encourage users to
create more engaging and attractive animations.
parent 0d5ee056
...@@ -522,16 +522,295 @@ class Curves { ...@@ -522,16 +522,295 @@ class Curves {
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in.mp4} /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in.mp4}
static const Cubic easeIn = Cubic(0.42, 0.0, 1.0, 1.0); static const Cubic easeIn = Cubic(0.42, 0.0, 1.0, 1.0);
/// A cubic animation curve that starts slowly and ends quickly. This is
/// similar to [Curves.easeIn], but with sinusoidal easing for a slightly less
/// abrupt beginning and end. Nonetheless, the result is quite gentle and is
/// hard to distinguish from [Curves.linear] at a glance.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_sine.mp4}
static const Cubic easeInSine = Cubic(0.47, 0, 0.745, 0.715);
/// A cubic animation curve that starts slowly and ends quickly. Based on a
/// quadratic equation where `f(t) = t²`, this is effectively the inverse of
/// [Curves.decelerate].
///
/// Compared to [Curves.easeInSine], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_quad.mp4}
static const Cubic easeInQuad = Cubic(0.55, 0.085, 0.68, 0.53);
/// A cubic animation curve that starts slowly and ends quickly. This curve is
/// based on a cubic equation where `f(t) = t³`. The result is a safe sweet
/// spot when choosing a curve for widgets animating off the viewport.
///
/// Compared to [Curves.easeInQuad], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_cubic.mp4}
static const Cubic easeInCubic = Cubic(0.55, 0.055, 0.675, 0.19);
/// A cubic animation curve that starts slowly and ends quickly. This curve is
/// based on a quartic equation where `f(t) = t⁴`.
///
/// Animations using this curve or steeper curves will benefit from a longer
/// duration to avoid motion feeling unnatural.
///
/// Compared to [Curves.easeInCubic], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_quart.mp4}
static const Cubic easeInQuart = Cubic(0.895, 0.03, 0.685, 0.22);
/// A cubic animation curve that starts slowly and ends quickly. This curve is
/// based on a quintic equation where `f(t) = t⁵`.
///
/// Compared to [Curves.easeInQuart], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_quint.mp4}
static const Cubic easeInQuint = Cubic(0.755, 0.05, 0.855, 0.06);
/// A cubic animation curve that starts slowly and ends quickly. This curve is
/// based on an exponential equation where `f(t) = 2¹⁰⁽ᵗ⁻¹⁾`.
///
/// Using this curve can give your animations extra flare, but a longer
/// duration may need to be used to compensate for the steepness of the curve.
///
/// Compared to [Curves.easeInQuint], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_expo.mp4}
static const Cubic easeInExpo = Cubic(0.95, 0.05, 0.795, 0.035);
/// A cubic animation curve that starts slowly and ends quickly. This curve is
/// effectively the bottom-right quarter of a circle.
///
/// Like [Curves.easeInExpo], this curve is fairly dramatic and will reduce
/// the clarity of an animation if not given a longer duration.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_circ.mp4}
static const Cubic easeInCirc = Cubic(0.6, 0.04, 0.98, 0.335);
/// A cubic animation curve that starts slowly and ends quickly. This curve
/// is similar to [Curves.elasticIn] in that it overshoots its bounds before
/// reaching its end. Instead of repeated swinging motions before ascending,
/// though, this curve overshoots once, then continues to ascend.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_back.mp4}
static const Cubic easeInBack = Cubic(0.6, -0.28, 0.735, 0.045);
/// A cubic animation curve that starts quickly and ends slowly. /// A cubic animation curve that starts quickly and ends slowly.
/// ///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out.mp4} /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out.mp4}
static const Cubic easeOut = Cubic(0.0, 0.0, 0.58, 1.0); static const Cubic easeOut = Cubic(0.0, 0.0, 0.58, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends slowly. /// A cubic animation curve that starts quickly and ends slowly. This is
/// similar to [Curves.easeOut], but with sinusoidal easing for a slightly
/// less abrupt beginning and end. Nonetheless, the result is quite gentle and
/// is hard to distinguish from [Curves.linear] at a glance.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_sine.mp4}
static const Cubic easeOutSine = Cubic(0.39, 0.575, 0.565, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This is
/// effectively the same as [Curves.decelerate], only simulated using a cubic
/// bezier function.
///
/// Compared to [Curves.easeOutSine], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_quad.mp4}
static const Cubic easeOutQuad = Cubic(0.25, 0.46, 0.45, 0.94);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// a flipped version of [Curves.easeInCubic].
///
/// The result is a safe sweet spot when choosing a curve for animating a
/// widget's position entering or already inside the viewport.
///
/// Compared to [Curves.easeOutQuad], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_cubic.mp4}
static const Cubic easeOutCubic = Cubic(0.215, 0.61, 0.355, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// a flipped version of [Curves.easeInQuart].
///
/// Animations using this curve or steeper curves will benefit from a longer
/// duration to avoid motion feeling unnatural.
///
/// Compared to [Curves.easeOutCubic], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_quart.mp4}
static const Cubic easeOutQuart = Cubic(0.165, 0.84, 0.44, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// a flipped version of [Curves.easeInQuint].
///
/// Compared to [Curves.easeOutQuart], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_quint.mp4}
static const Cubic easeOutQuint = Cubic(0.23, 1.0, 0.32, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// a flipped version of [Curves.easeInExpo]. Using this curve can give your
/// animations extra flare, but a longer duration may need to be used to
/// compensate for the steepness of the curve.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_expo.mp4}
static const Cubic easeOutExpo = Cubic(0.19, 1.0, 0.22, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// effectively the top-left quarter of a circle.
///
/// Like [Curves.easeOutExpo], this curve is fairly dramatic and will reduce
/// the clarity of an animation if not given a longer duration.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_circ.mp4}
static const Cubic easeOutCirc = Cubic(0.075, 0.82, 0.165, 1.0);
/// A cubic animation curve that starts quickly and ends slowly. This curve is
/// similar to [Curves.elasticOut] in that it overshoots its bounds before
/// reaching its end. Instead of repeated swinging motions after ascending,
/// though, this curve only overshoots once.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_out_back.mp4}
static const Cubic easeOutBack = Cubic(0.175, 0.885, 0.32, 1.275);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly.
/// ///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out.mp4} /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out.mp4}
static const Cubic easeInOut = Cubic(0.42, 0.0, 0.58, 1.0); static const Cubic easeInOut = Cubic(0.42, 0.0, 0.58, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This is similar to [Curves.easeInOut], but with sinusoidal easing
/// for a slightly less abrupt beginning and end.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_sine.mp4}
static const Cubic easeInOutSine = Cubic(0.445, 0.05, 0.55, 0.95);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInQuad] as the first
/// half, and [Curves.easeOutQuad] as the second.
///
/// Compared to [Curves.easeInOutSine], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_quad.mp4}
static const Cubic easeInOutQuad = Cubic(0.455, 0.03, 0.515, 0.955);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInCubic] as the first
/// half, and [Curves.easeOutCubic] as the second.
///
/// The result is a safe sweet spot when choosing a curve for a widget whose
/// initial and final positions are both within the viewport.
///
/// Compared to [Curves.easeInOutQuad], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_cubic.mp4}
static const Cubic easeInOutCubic = Cubic(0.645, 0.045, 0.355, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInQuart] as the first
/// half, and [Curves.easeOutQuart] as the second.
///
/// Animations using this curve or steeper curves will benefit from a longer
/// duration to avoid motion feeling unnatural.
///
/// Compared to [Curves.easeInOutCubic], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_quart.mp4}
static const Cubic easeInOutQuart = Cubic(0.77, 0, 0.175, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInQuint] as the first
/// half, and [Curves.easeOutQuint] as the second.
///
/// Compared to [Curves.easeInOutQuart], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_quint.mp4}
static const Cubic easeInOutQuint = Cubic(0.86, 0, 0.07, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly.
///
/// Since this curve is arrived at with an exponential function, the midpoint
/// is exceptionally steep. Extra consideration should be taken when designing
/// an animation using this.
///
/// Compared to [Curves.easeInOutQuint], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_expo.mp4}
static const Cubic easeInOutExpo = Cubic(1.0, 0, 0, 1.0);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInCirc] as the first
/// half, and [Curves.easeOutCirc] as the second.
///
/// Like [Curves.easeInOutExpo], this curve is fairly dramatic and will reduce
/// the clarity of an animation if not given a longer duration.
///
/// Compared to [Curves.easeInOutExpo], this curve is slightly steeper.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_circ.mp4}
static const Cubic easeInOutCirc = Cubic(0.785, 0.135, 0.15, 0.86);
/// A cubic animation curve that starts slowly, speeds up, and then and ends
/// slowly. This curve can be imagined as [Curves.easeInBack] as the first
/// half, and [Curves.easeOutBack] as the second.
///
/// Since two curves are used as a basis for this curve, the resulting
/// animation will overshoot its bounds twice before reaching its end - first
/// by exceeding its lower bound, then exceeding its upper bound and finally
/// descending to its final position.
///
/// Derived from Robert Penner’s easing functions.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease_in_out_back.mp4}
static const Cubic easeInOutBack = Cubic(0.68, -0.55, 0.265, 1.55);
/// A curve that starts quickly and eases into its final position. /// A curve that starts quickly and eases into its final position.
/// ///
/// Over the course of the animation, the object spends more time near its /// Over the course of the animation, the object spends more time near its
......
...@@ -45,16 +45,42 @@ void main() { ...@@ -45,16 +45,42 @@ void main() {
test('Curve is continuous', () { test('Curve is continuous', () {
assertMaximumSlope(Curves.linear, 20.0); assertMaximumSlope(Curves.linear, 20.0);
assertMaximumSlope(Curves.decelerate, 20.0); assertMaximumSlope(Curves.decelerate, 20.0);
assertMaximumSlope(Curves.fastOutSlowIn, 20.0);
assertMaximumSlope(Curves.bounceIn, 20.0); assertMaximumSlope(Curves.bounceIn, 20.0);
assertMaximumSlope(Curves.bounceOut, 20.0); assertMaximumSlope(Curves.bounceOut, 20.0);
assertMaximumSlope(Curves.bounceInOut, 20.0); assertMaximumSlope(Curves.bounceInOut, 20.0);
assertMaximumSlope(Curves.elasticOut, 20.0); assertMaximumSlope(Curves.elasticOut, 20.0);
assertMaximumSlope(Curves.elasticInOut, 20.0); assertMaximumSlope(Curves.elasticInOut, 20.0);
assertMaximumSlope(Curves.ease, 20.0); assertMaximumSlope(Curves.ease, 20.0);
assertMaximumSlope(Curves.easeIn, 20.0); assertMaximumSlope(Curves.easeIn, 20.0);
assertMaximumSlope(Curves.easeInSine, 20.0);
assertMaximumSlope(Curves.easeInQuad, 20.0);
assertMaximumSlope(Curves.easeInCubic, 20.0);
assertMaximumSlope(Curves.easeInQuart, 20.0);
assertMaximumSlope(Curves.easeInQuint, 20.0);
assertMaximumSlope(Curves.easeInExpo, 20.0);
assertMaximumSlope(Curves.easeInCirc, 20.0);
assertMaximumSlope(Curves.easeOut, 20.0); assertMaximumSlope(Curves.easeOut, 20.0);
assertMaximumSlope(Curves.easeOutSine, 20.0);
assertMaximumSlope(Curves.easeOutQuad, 20.0);
assertMaximumSlope(Curves.easeOutCubic, 20.0);
assertMaximumSlope(Curves.easeOutQuart, 20.0);
assertMaximumSlope(Curves.easeOutQuint, 20.0);
assertMaximumSlope(Curves.easeOutExpo, 20.0);
assertMaximumSlope(Curves.easeOutCirc, 20.0);
// Curves.easeInOutExpo is discontinuous at its midpoint, so not included
// here
assertMaximumSlope(Curves.easeInOut, 20.0); assertMaximumSlope(Curves.easeInOut, 20.0);
assertMaximumSlope(Curves.fastOutSlowIn, 20.0); assertMaximumSlope(Curves.easeInOutSine, 20.0);
assertMaximumSlope(Curves.easeInOutQuad, 20.0);
assertMaximumSlope(Curves.easeInOutCubic, 20.0);
assertMaximumSlope(Curves.easeInOutQuart, 20.0);
assertMaximumSlope(Curves.easeInOutQuint, 20.0);
assertMaximumSlope(Curves.easeInOutCirc, 20.0);
}); });
void expectStaysInBounds(Curve curve) { void expectStaysInBounds(Curve curve) {
...@@ -115,6 +141,23 @@ void main() { ...@@ -115,6 +141,23 @@ void main() {
expect(bounds[1], greaterThan(1.0)); expect(bounds[1], greaterThan(1.0));
}); });
test('Back overshoots its bounds', () {
expect(Curves.easeInBack, hasOneLineDescription);
expect(Curves.easeOutBack, hasOneLineDescription);
expect(Curves.easeInOutBack, hasOneLineDescription);
List<double> bounds;
bounds = estimateBounds(Curves.easeInBack);
expect(bounds[0], lessThan(0.0));
expect(bounds[1], lessThanOrEqualTo(1.0));
bounds = estimateBounds(Curves.easeOutBack);
expect(bounds[0], greaterThanOrEqualTo(0.0));
expect(bounds[1], greaterThan(1.0));
bounds = estimateBounds(Curves.easeInOutBack);
expect(bounds[0], lessThan(0.0));
expect(bounds[1], greaterThan(1.0));
});
test('Decelerate does so', () { test('Decelerate does so', () {
expect(Curves.decelerate, hasOneLineDescription); expect(Curves.decelerate, hasOneLineDescription);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment