Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cubic Bezier Animation Easing (ease-in-out) #2717

Closed
wants to merge 11 commits into from
Closed

Conversation

aevyrie
Copy link
Contributor

@aevyrie aevyrie commented Feb 11, 2023

Extends the existing animation manager to add cubic Bezier and custom function easing; adds presets from CSS and Material Design, and switches widgets to use easing instead of linear by default.

⚠️ Captured with exaggerated animation duration for effect: ⚠️

2023-02-11.22-38-44.mp4

The default animation duration has been bumped up slightly to account for the nonlinear nature of the new easing, with the intent of keeping the perceived snappiness the same, while allowing a bit more time for the smooth deceleration at the end of animations.

I've included some useful presets that are used commonly elsewhere, and in this case I've taken from the W3C spec directly.

The new easing enum:

/// Easing shaping functions
#[derive(Clone, Copy, Debug)]
pub enum Ease {
    /// Simple linear easing.
    Linear,
    /// Cubic Bezier curve, corresponding to the control points `P1.x`, `P1.y`, `P2.x`, `P2.y`.
    /// Extremely versatile for smooth animation.
    CubicBezier(f32, f32, f32, f32),
    /// User defined shaping function. Given a `time` within `0..=1`, this function should remap to
    /// a new value, usually - but not necessarily -  within the same range.
    Equation(fn(f32) -> f32),
}

Implementation Notes

I decided to write a cubic Bezier implementation, instead of reusing the existing Bezier code used for rendering curves. The reasons for this:

  • For use in animations, you can make some simplifying assumptions to speed things up. Namely, you don't need four control points as inputs, as the first and last are at (0,0) and (1,1) respectively. Additionally, there is no need to fill the Bezier curve.
  • The implementation is short and readable, at only ~50LOC
  • For animation, this needs functionality that doesn't exist in the rendering of Beziers, at least that I could find. In particular, animation requires a fast solve to find the parameter t given the input time on the x axis, which can then be used to find the output value y. I chose Raphson-Newton as this appears to be used in browsers and converges within 1e-7 with <= 8 iterations. More complex methods can be used if needed, but this approach is robust, fast, and simple.

@aevyrie aevyrie changed the title Simple Bezier and Custom Easing Cubic Bezier and Custom Easing Feb 12, 2023
@aevyrie
Copy link
Contributor Author

aevyrie commented Feb 13, 2023

An open question for me, is whether this should be serializable and part of Style. If so, that would mean we might need to remove Ease::Equation as function pointers cannot be serialized. I'm also not certain how we would break this up:

  • Have a single Ease setting globally, like the animation_duration?
  • Ease per group, e.g. buttons, collapsing headers, window collapse, window fade?

I also haven't included color animation, though this does seem like a natural extension. It probably makes sense to leave that out of scope, though I would be happy to work on that if it would be valuable.

@Aceeri
Copy link

Aceeri commented Feb 15, 2023

If so, that would mean we might need to remove Ease::Equation as function pointers cannot be serialized.

We could make the Equation(Box<dyn EasingFunction>) where

pub trait EasingFunction: Serialize + Deserialize {
    fn ease(f32) -> f32;
}

So that people have to wrap their easing functions in a marker struct like so:

#[derive(Serialize, Deserialize)]
pub struct CustomEasing;

impl EasingFunction for CustomEasing {
    fn ease(t: f32) -> f32 { ... }
}

@aevyrie
Copy link
Contributor Author

aevyrie commented Jun 6, 2023

Is there anything I can do to move this forward? 🙂

If it helps the review process, note that all the substantial changes are in animation_manager.rs. Everything else is just updating examples/widgets to use the new feature.

@aevyrie aevyrie changed the title Cubic Bezier and Custom Easing Cubic Bezier Animation Easing (ease-in-out) Jun 6, 2023
@aevyrie aevyrie mentioned this pull request Oct 30, 2024
@aevyrie aevyrie closed this Oct 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants