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

[css-timing] spring() timing function #280

Open
grorg opened this issue Jul 6, 2016 · 11 comments
Open

[css-timing] spring() timing function #280

grorg opened this issue Jul 6, 2016 · 11 comments
Assignees
Labels
css-easing-2 Current Work

Comments

@grorg
Copy link
Contributor

grorg commented Jul 6, 2016

Originally sent to www-style: http://www.w3.org/mid/1F5F295B-DF6C-485F-ACFC-64F2C6BE5E41@apple.com
(there is some discussion on the list that I won't copy into this description - please read it on the archives)

Proposal: spring() timing function in CSS and Web Animations

We propose adding a new timing function for transitions and animations to
simulate the effect of a spring-based motion between the endpoints.

Over the past few years, Apple's designers have moved to more physically-based
motion effects. Not only do these look more natural and fun, they also are
often easier to tweak to get a desired effect. By far the most common type of
motion we've seen is a simulation of a spring.

There are a lot of online resources discussing why this is good. Here is one of
my favourites: Creating Animations and Interactions with Physical
Models --> https://iamralpht.github.io/physics/

We're still discussing what is the best way to expose springy animations.
Some internal feedback has suggested that our parameterisation below is
too hard to author, and that we should favor a more simple F = -kx approach.
I'm sure there are lots of people reading who have opinions. Please
share these opinions!

Here is what we propose today as a starting point:

spring(mass stiffness damping initialVelocity)

Simulate a spring using the solving algorithm defined by this JavaScript
function [1].

mass: The mass of the object attached to the end of the spring. Must be greater
than 0. Defaults to 1.

stiffness: The spring stiffness coefficient. Must be greater than 0.
Defaults to 100.

damping: The damping coefficient. Must be greater than or equal to 0.
Defaults to 10.

initialVelocity: The initial velocity of the object attached to the spring.
Defaults to 0, which represents an unmoving object. Negative values
represent the object moving away from the spring attachment point, positive
values represent the object moving towards the spring attachment point.

NOTE: The definition of spring() above uses spaces to separate parameters
because "So I tied an onion to my belt, which was the style at the
time" [2]. Since all the other timing functions are comma-separated, maybe
it is better to be consistent?

What's unusual about this form of timing function is that the animation
effect is now independent of its duration. The spring timing function
completely controls how the animation reaches its end point, and certain
parameter values can produce an animation that does not settle at the end
point before the animation duration expires (technically they never
completely settle).

We therefore also propose a new keyword for duration: "auto", which means
the duration will be calculated to be the time where the animation has settled.

NOTE: Lots of hand-waving here at the moment. Firstly, what "settle" means
to most people is dependent on the type of animation, and the size of the
animating object, and the distance being animated over. Secondly, we'd need to
describe how this works for a keyframed animation, where the duration applies
over all the keyframes.

The spring() timing function as described above has been implemented in
WebKit. It is currently exposed in the Safari Technology Preview, although note
that the current implementation does not handle optional parameters (you have
to specify them all). It's not exposed in regular Safari builds - we'll consider
that if we can reach consensus here.

For what it's worth, the implementation in WebKit was fairly simple. We don't
think this is a big burden to browsers.

Meanwhile, here is a demo page that has the effect implemented
in JavaScript [3]

Of course, all this should apply to Web Animations... left as an exercise
for the reader :)

[1] https://webkit.org/demos/spring/spring.js
[2] https://frinkiac.com/?q=style%20at%20the%20time
[3] https://webkit.org/demos/spring/

With lots of love,

weinig and dino

@grorg
Copy link
Contributor Author

grorg commented Jul 6, 2016

It seems that #229 is related

@shans
Copy link
Contributor

shans commented Jul 14, 2016

I think there's no need for both a stiffness and a mass, particularly if we aren't trying to get all physical with real units 'n stuff.

The spring equation (Hooke's Law) is F = kx - but F is just ma, so we have
a = (k/m) x - i.e. the acceleration on the object is proportional to the distance away from the resting point.

You should just expose that relationship, rather than two values that lead to redundancy.

Damping uses stiffness and mass too - but it's probably better just to expose the zeta directly, particularly because this allows people to easily choose between overdamped, critically damped, and underdamped.

@shans
Copy link
Contributor

shans commented Jul 14, 2016

A bigger issue - this doesn't feel like a timing function as it doesn't modify the course of the animation over a fixed time (which is why you've proposed the 'auto' duration, which is scary because what does that mean for animations that aren't spring functions?).

An alternative (switching to Web Animations terms for a second) might be to replace the KeyframeEffect with a SpringEffect? I don't know what this would mean in terms of CSS syntax though.

@othermaciej
Copy link
Member

If you expose zeta instead of the damping coefficient then perhaps it would make more sense to expose the natural frequency (ω0) instead of k/m. Besides the fact that these choices may make spring parameters easier to understand and author, it is also convenient that zeta is dimensionless and omega-nought is a frequency, which CSS has a unit for.

@vidhill
Copy link

vidhill commented Jul 18, 2016

I have added a proposition as to how this and any other scripted easing function could be defined here, #229 (comment) would like to hear your thoughts

@birtles birtles added the css-easing-2 Current Work label Jul 3, 2018
@birtles birtles changed the title [css-transitions] spring() timing function [css-timing] spring() timing function Jul 3, 2018
@birtles
Copy link
Contributor

birtles commented Jul 3, 2018

Moving this to css-timing.

@birtles birtles removed the css-animations-1 Current Work label Jul 3, 2018
@samhenrigold
Copy link

@birtles Has this gotten any further consideration?

@birtles
Copy link
Contributor

birtles commented Aug 5, 2021

@birtles Has this gotten any further consideration?

@samhenrigold Yes, you can follow the discussion in #229. There's a very pragmatic and promising proposal from @jakearchibald starting here: #229 (comment)

@rihok
Copy link

rihok commented Mar 11, 2022

@birtles Has this gotten any further consideration?

@samhenrigold Yes, you can follow the discussion in #229. There's a very pragmatic and promising proposal from @jakearchibald starting here: #229 (comment)

The proposal would allow pre-calculating spring-like motion in discreete steps, but not "springs" as velocity driven value changes over time. Springs are useful because they retain the velocity throughout value changes, so the transition can look smooth regardless of how often the value is changed. That's not possible to define in discreete steps, so I'd say the proposal for a spring() function would still need further consideration. Perhaps I'm missing some discussions around this though.

Edit:
It does appear that the Safari implementation isn't tracking velocity throughout changes actually. Seems like the velocity is reset on every change, which severely limits its usefulness.

@jakearchibald
Copy link
Contributor

Yeah, spring() kinda sits uncomfortably between a regular easing and a physics system. Eg, it doesn't take into consideration the movement of parent objects, and it'd likely be too complicated to do so.

@rihok
Copy link

rihok commented Mar 14, 2022

I don't think it needs to be that complicated. Taking into account parent velocity wouldn't even make sense for something like color interpolation for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-easing-2 Current Work
Projects
None yet
Development

No branches or pull requests

9 participants