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

Subtle tweaks to spring animations #2627

Merged
merged 1 commit into from
May 4, 2019
Merged

Subtle tweaks to spring animations #2627

merged 1 commit into from
May 4, 2019

Commits on Apr 30, 2019

  1. Subtle tweaks to spring animations

    Use verlet-style integration for spring animations. Rather than keeping track of "value" and velocity over time, keep track of value and previous-value, and derive velocity from the delta every tick. This has a few benefits, including greater stability (position and velocity can't drift) and simplifying signature of tick_spring (no need to pass velocity back up).
    
    Pulling "settled" flag out of the return signature as well means return value is just "next value", simplifying code mapping over objects and arrays, and eliminating duplicated code across get_initial_velocity, get_threshold and tick_spring.
    
    Refactored "threshold" calcs, extremely inexpensive to do inline in tick_spring rather than create a parallel structure. Also fixes a rare pathological case where springs will never settle (reading through the code, could happen if velocity was non-zero during a set() where target==current, threshold will be calculated to be zero and settled will always be set to false, leading to infinite animations).
    
    Functional changes:
    
    In my experience dealing with spring animations, there are a handful of edge-cases where it is nice to have library support. 99% of the time, the only times you'd want to fudge 'stiffness' and 'damping' is during a live interaction (e.g. dragging something around). By providing an idiomatic mechanism hopefully the code around dealing with that could be simpler.
    
    I propose an additional "options" parameter to 'set()' and 'update()'.
    
    If passed {hard:true} the set will be considered a "hard" set, where you want the value to be set to the target value immediately. This could be extremely useful when implementing dragging for instance.
    
    If passed {soft:true} or {soft:<duration>}, the set will be considered a "soft" set, where momentum will be preserved for some duration before settling. This could be useful when implementing "throwing", e.g. after a drag, on mouseup, 'soft set' to some position and the user's previous momentum will be honored before settling down.
    
    Technically momentum preservation happens to a degree now, but aggressive stiffness and/or damping values make it nearly unapparent. This handles the case where you may want more aggressive or heavily underdamped springs but without the apparent velocity discontinuity that happens on throw. (As a real example, in FaceTime, note behavior when tossing around the picture-in-picture, or the iPhone X gestural behavior when tossing apps back to the home screen).
    
    Internally this is implemented by temporarily setting mass to infinity and ramping back to normal over some duration.
    
    "Hard sets" are also special-cased to trigger a same-frame set and fulfilment, leading to more responsive dragging. Best case is a one frame improvement in drag latency (noticed in Safari). This also handles the "old way" method of munging 'stiffness' and 'damping' to 1, so the improvement applies to existing code.
    lorenbrichter committed Apr 30, 2019
    Configuration menu
    Copy the full SHA
    d2b202d View commit details
    Browse the repository at this point in the history