[css-transitions] Proposal and RFC: spring() timing function

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[css-transitions] Proposal and RFC: spring() timing function

Dean Jackson-7
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




Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:

> 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.

These all look like they're <number>s? Is that intentional? Can they
be typed in some way?  In particular, it looks like stiffness might be
amenable to becoming <percentage>?

> 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?

I have mixed opinions. On the one hand, I want us to move more towards
"functions are just named chunks of CSS syntax, and CSS syntax doesn't
use commas just to separate values". On the other hand, consistency
with existing stuff.  ¯\_(ツ)_/¯

> 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).

Is it possible to get the opposite behavior, and leave one or more of
the parameters undefined, then auto-compute them from the desired
time?  (Just curious, I don't have a use-case in mind for this.)  The
equation looks annoyingly non-linear, but I dunno.

> 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.

"auto" seems reasonable here, but we also have to define what it means
for all the other timing functions.

> 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.

Are the parameters currently arranged in the most useful order for
defaulting? If they're all untyped numbers, the only way to omit is
in-order from the end...

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
In reply to this post by Dean Jackson-7
On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
> [1] https://webkit.org/demos/spring/spring.js

Typo on line 51: `thism_B` makes the critically-/over-damped case fail.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Dean Jackson-7

> On 1 Jul 2016, at 7:41 AM, Tab Atkins Jr. <[hidden email]> wrote:
>
> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>> [1] https://webkit.org/demos/spring/spring.js
>
> Typo on line 51: `thism_B` makes the critically-/over-damped case fail.

👀‼️ Fixed. Thanks.

Dean


Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Dean Jackson-7
In reply to this post by Tab Atkins Jr.

> On 1 Jul 2016, at 7:38 AM, Tab Atkins Jr. <[hidden email]> wrote:
>
> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>> 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.
>
> These all look like they're <number>s? Is that intentional? Can they
> be typed in some way?  In particular, it looks like stiffness might be
> amenable to becoming <percentage>?

They are all numbers. I don't think percentage makes sense - what are
they are percentage of?

This brings up the question a few people have asked: what are the units
for all these? The answer is it doesn't really matter :) The output value
is determined by the parameters fed to the solving function. You could
assign some units if you like, but it's not like initialVelocity is in
pixels per second.

>
>> 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?
>
> I have mixed opinions. On the one hand, I want us to move more towards
> "functions are just named chunks of CSS syntax, and CSS syntax doesn't
> use commas just to separate values". On the other hand, consistency
> with existing stuff.  ¯\_(ツ)_/¯

I don't mind either way. I'm happy to accept spaces for the other
timing functions too, if someone wants to push that change to the specification.

>
>> 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).
>
> Is it possible to get the opposite behavior, and leave one or more of
> the parameters undefined, then auto-compute them from the desired
> time?  (Just curious, I don't have a use-case in mind for this.)  The
> equation looks annoyingly non-linear, but I dunno.

The problem here is that the equation never technically settles, so we'd
have to pick some epsilon value for distance from end point and rate of change,
and then call that the end. I'm not sure how hard it would be to work
back from that to a set of inputs, but I think if we fix some of them
to default values we should be able to auto-compute at least one.

We could pick another formula that is more amenable to duration-based
springs.

However, there is some criticism against coding an animation like this
purely on duration:
https://medium.com/@flyosity/your-spring-animations-are-bad-and-it-s-probably-apple-s-fault-784932e51733

>
>> 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.
>
> "auto" seems reasonable here, but we also have to define what it means
> for all the other timing functions.

At the moment we were thinking that auto only makes sense for springs. I
am happy for it to be 0 or some other value if we'd rather it do something.

>
>> 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.
>
> Are the parameters currently arranged in the most useful order for
> defaulting? If they're all untyped numbers, the only way to omit is
> in-order from the end...


Yeah. This is something we were hoping to get feedback on.

Dean



Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Tab Atkins Jr.

> On Jun 30, 2016, at 2:38 PM, Tab Atkins Jr. <[hidden email]> wrote:
>
> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>> 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.
>
> These all look like they're <number>s? Is that intentional? Can they
> be typed in some way?  In particular, it looks like stiffness might be
> amenable to becoming <percentage>?

The canonical units for these values in a damped spring model would be
mass: kilogram
stiffness: Newton/meter (force over distance)
damping: Newton-second/meter (force over velocity)
initialVelocity: meter/second

I think CSS does not support these units, and it's not clear that it would make sense to add them. None of them is sensibly regarded as a percentage.

(I'd guess Sam and Dean may have rescaled these but any units for these quantities in a spring model would differ by at most a constant factor. One possibility that seems appealing is to give velocity in px/s rather than m/s, and rescale other units appropriately.

Regards,
Maciej
Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Dean Jackson-7

> On 1 Jul 2016, at 11:12 AM, Maciej Stachowiak <[hidden email]> wrote:
>
>>
>> On Jun 30, 2016, at 2:38 PM, Tab Atkins Jr. <[hidden email]> wrote:
>>
>> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>>> 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.
>>
>> These all look like they're <number>s? Is that intentional? Can they
>> be typed in some way?  In particular, it looks like stiffness might be
>> amenable to becoming <percentage>?
>
> The canonical units for these values in a damped spring model would be
> mass: kilogram
> stiffness: Newton/meter (force over distance)
> damping: Newton-second/meter (force over velocity)
> initialVelocity: meter/second
>
> I think CSS does not support these units, and it's not clear that it would make sense to add them. None of them is sensibly regarded as a percentage.
>
> (I'd guess Sam and Dean may have rescaled these

No, we didn't.

> but any units for these quantities in a spring model would differ by at most a constant factor. One possibility that seems appealing is to give velocity in px/s rather than m/s, and rescale other units appropriately.

But it's not always pixels you're moving. e.g. hue degrees per second? :)

That's why I think it's just not worth trying to explain it. The inputs go into a function along with the elapsed time and out comes a value that should eventually move from 0 to 1 (but isn't restricted to that range during the animation). Twiddle the values until you get something that looks good.

Dean


Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Dean Jackson-7

> On Jun 29, 2016, at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>
> 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.

Would it make sense to also have an initial displacement? I'd guess an animation for something snapping back after you pull it best modeled as a critically damped spring with no initial velocity but a nonzero initial displacement. At the very least it seems weird for this to be missing.

While the mass unit here is arbitrary, perhaps the implied time and distance units don't have to be, so perhaps they should be something logical. For example, if an object is already moving at some speed across the screen and you want it to act as if it ran into a spring to stop, it might be nice to know how to pass in your initial velocity.

Regards,
Maciej



Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Dean Jackson-7

> On Jun 30, 2016, at 6:19 PM, Dean Jackson <[hidden email]> wrote:
>
>
>> On 1 Jul 2016, at 11:12 AM, Maciej Stachowiak <[hidden email]> wrote:
>>
>>>
>>> On Jun 30, 2016, at 2:38 PM, Tab Atkins Jr. <[hidden email]> wrote:
>>>
>>> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>>>> 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.
>>>
>>> These all look like they're <number>s? Is that intentional? Can they
>>> be typed in some way?  In particular, it looks like stiffness might be
>>> amenable to becoming <percentage>?
>>
>> The canonical units for these values in a damped spring model would be
>> mass: kilogram
>> stiffness: Newton/meter (force over distance)
>> damping: Newton-second/meter (force over velocity)
>> initialVelocity: meter/second
>>
>> I think CSS does not support these units, and it's not clear that it would make sense to add them. None of them is sensibly regarded as a percentage.
>>
>> (I'd guess Sam and Dean may have rescaled these
>
> No, we didn't.
>
>> but any units for these quantities in a spring model would differ by at most a constant factor. One possibility that seems appealing is to give velocity in px/s rather than m/s, and rescale other units appropriately.
>
> But it's not always pixels you're moving. e.g. hue degrees per second? :)

Spring animation of a color parameter? Mind=blown.

>
> That's why I think it's just not worth trying to explain it. The inputs go into a function along with the elapsed time and out comes a value that should eventually move from 0 to 1 (but isn't restricted to that range during the animation). Twiddle the values until you get something that looks good.

But, as I said in my other email, you may want to chain a constant velocity animation into a spring animation, so at that point the velocity becomes meaningful because you want continuity.

BTW a spring stiffness constant of 0 with nonzero damping would also be useful to model deceleration due to friction (I think friction basically works like spring damping with no spring). In this case too the initial velocity is meaningful.

Technically, CSS defines the number of px per meter but I am not sure if that is even the mapping you use.

Regards,
Maciej


Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Maciej Stachowiak

On Jun 30, 2016, at 6:20 PM, Maciej Stachowiak <[hidden email]> wrote:


On Jun 29, 2016, at 9:32 PM, Dean Jackson <[hidden email]> wrote:

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.

Would it make sense to also have an initial displacement? I'd guess an animation for something snapping back after you pull it best modeled as a critically damped spring with no initial velocity but a nonzero initial displacement. At the very least it seems weird for this to be missing.

I just realized that the difference between the start position and the end position must logically be the initial displacement.

Regards,
Maciej

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
In reply to this post by Dean Jackson-7
On Thu, Jun 30, 2016 at 6:05 PM, Dean Jackson <[hidden email]> wrote:

> On 1 Jul 2016, at 7:38 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>>> 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.
>>
>> These all look like they're <number>s? Is that intentional? Can they
>> be typed in some way?  In particular, it looks like stiffness might be
>> amenable to becoming <percentage>?
>
> They are all numbers. I don't think percentage makes sense - what are
> they are percentage of?

I don't know - I was asking because it seemed like a stiffness with a
min of 0 and a default of 100 felt like something that might be a
percentage.

> This brings up the question a few people have asked: what are the units
> for all these? The answer is it doesn't really matter :) The output value
> is determined by the parameters fed to the solving function. You could
> assign some units if you like, but it's not like initialVelocity is in
> pixels per second.

And given the reminder you provided that you can be animating anything
with a spring function, such as color, I suppose units would have to
be oddly abstract anyway.

Okay, so the main benefits of unitted values is that they (a)
distinguish values from each other, so you can more easily omit
arbitrary bits, and (b) help identify the values mnemonically.  The
current "everything is a number" fails on both counts, as the only way
to identify things is positionally, so you can only omit from the end,
and you'll have to look up what the values are every time.

I think we shouldn't ignore these benefits. We can recapture them with
explicit labelling, by putting in keywords before each of the values.
That way you can just do `spring(mass 2 velocity 5)` and it'll fill in
the defaults for the rest!

(Alternate syntax: use units for these, like `spring(2mass
5velocity)`. Stronger connection between value and type, but also
maybe weird? Unsure.)

(Second alternate syntax: finally invent "named arguments" for real,
like some people have been agitating for for a while.  `spring(mass:
2; velocity: 5;)`?  To be less weird we'd have then go and backport
this to other functions. Probably a decent idea? Need to noodle on
syntax more, look at several different functions that use syntax
differently.

>>> 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).
>>
>> Is it possible to get the opposite behavior, and leave one or more of
>> the parameters undefined, then auto-compute them from the desired
>> time?  (Just curious, I don't have a use-case in mind for this.)  The
>> equation looks annoyingly non-linear, but I dunno.
>
> The problem here is that the equation never technically settles, so we'd
> have to pick some epsilon value for distance from end point and rate of change,
> and then call that the end. I'm not sure how hard it would be to work
> back from that to a set of inputs, but I think if we fix some of them
> to default values we should be able to auto-compute at least one.

Right, but "the duration never technically settles" applies to
"specify all of them and use an auto duration", too.

> We could pick another formula that is more amenable to duration-based
> springs.
>
> However, there is some criticism against coding an animation like this
> purely on duration:
> https://medium.com/@flyosity/your-spring-animations-are-bad-and-it-s-probably-apple-s-fault-784932e51733

That criticism is geared towards a bad API design that required you to
specify a *technically redundant* duration, and if you didn't specify
what the algo would have "naturally" provided you get an
unnatural-looking result.

I don't think it directly applies to "specify any four out of (the
four spring arguments) + duration, we'll auto-compute the fifth".
There might be other good arguments against that, maybe even closely
related ones, I dunno, but that article in particular doesn't argue
against this afaict.

>>
>>> 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.
>>
>> "auto" seems reasonable here, but we also have to define what it means
>> for all the other timing functions.
>
> At the moment we were thinking that auto only makes sense for springs. I
> am happy for it to be 0 or some other value if we'd rather it do something.

Yeah, I don't have a strong opinion on what it should be, just noting
that it needs to have *a* definition.  Matching the default 0s value
for t/a-duration is probably good, yeah.

>>> 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.
>>
>> Are the parameters currently arranged in the most useful order for
>> defaulting? If they're all untyped numbers, the only way to omit is
>> in-order from the end...
>
> Yeah. This is something we were hoping to get feedback on.

I addressed this up above.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
In reply to this post by Maciej Stachowiak
On Fri, Jul 1, 2016 at 12:29 AM, Maciej Stachowiak <[hidden email]> wrote:
> On Jun 30, 2016, at 6:20 PM, Maciej Stachowiak <[hidden email]> wrote:
>> Would it make sense to also have an initial displacement? I'd guess an
>> animation for something snapping back after you pull it best modeled as a
>> critically damped spring with no initial velocity but a nonzero initial
>> displacement. At the very least it seems weird for this to be missing.
>
> I just realized that the difference between the start position and the end
> position must logically be the initial displacement.

Right, if you want to "snap back", you just put your starting position
at the "stretched out" location, and then animate to the point you
want to "snap back" to.  Exactly what's in the demo right now, except
with start/end swapped.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Brad Kemper
In reply to this post by Dean Jackson-7


> On Jun 30, 2016, at 6:19 PM, Dean Jackson <[hidden email]> wrote:
>
>
>>> On 1 Jul 2016, at 11:12 AM, Maciej Stachowiak <[hidden email]> wrote:
>>>
>>>
>>> On Jun 30, 2016, at 2:38 PM, Tab Atkins Jr. <[hidden email]> wrote:
>>>
>>> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>>>> 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.
>>>
>>> These all look like they're <number>s? Is that intentional? Can they
>>> be typed in some way?  In particular, it looks like stiffness might be
>>> amenable to becoming <percentage>?
>>
>> The canonical units for these values in a damped spring model would be
>> mass: kilogram
>> stiffness: Newton/meter (force over distance)
>> damping: Newton-second/meter (force over velocity)
>> initialVelocity: meter/second
>>
>> I think CSS does not support these units, and it's not clear that it would make sense to add them. None of them is sensibly regarded as a percentage.
>>
>> (I'd guess Sam and Dean may have rescaled these
>
> No, we didn't.
>
>> but any units for these quantities in a spring model would differ by at most a constant factor. One possibility that seems appealing is to give velocity in px/s rather than m/s, and rescale other units appropriately.
>
> But it's not always pixels you're moving. e.g. hue degrees per second? :)
>
> That's why I think it's just not worth trying to explain it. The inputs go into a function along with the elapsed time and out comes a value that should eventually move from 0 to 1 (but isn't restricted to that range during the animation). Twiddle the values until you get something that looks good.
>
> Dean

For velocity, percentage per second makes a certain amount of sense to me, with it being a percentage of the distance between start and stop points. That "distance" could be along a color spectrum, for colors.
Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
In reply to this post by Dean Jackson-7
On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
> Secondly, we'd need to
> describe how this works for a keyframed animation, where the duration applies
> over all the keyframes.

This, I think, is the part that needs the most thought.  This really
is a pretty big change from the current model, because it seems to be
impossible to accurately chain a spring effect into anything else
unless you run the math yourself to determine the effective duration.
That suggests pushing forward the timetable on "sequence/parallel
animation groups in WebAnim and CSS" might be worthwhile.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Dean Jackson-7

> On 2 Jul 2016, at 8:06 AM, Tab Atkins Jr. <[hidden email]> wrote:
>
> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>> Secondly, we'd need to
>> describe how this works for a keyframed animation, where the duration applies
>> over all the keyframes.
>
> This, I think, is the part that needs the most thought.  This really
> is a pretty big change from the current model, because it seems to be
> impossible to accurately chain a spring effect into anything else
> unless you run the math yourself to determine the effective duration.
> That suggests pushing forward the timetable on "sequence/parallel
> animation groups in WebAnim and CSS" might be worthwhile.

Is it that important that spring() applies to keyframed animations
from the beginning? Springs are an emulation of a physical effect, and
it's rare that you'll combine that with a keyframe (which is an unnatural
effect).

Springs make more sense going between two points. e.g. transitions.

I think we can address keyframes, but it isn't urgent. At worst we can
leave it as is for now, which means that the keyframe would advance
once its duration slice has expired. This could be while the animation
is still springing, or well after it as settled.

Happy Friday (or Saturday)

Dean




Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
On Fri, Jul 1, 2016 at 3:14 PM, Dean Jackson <[hidden email]> wrote:

>> On 2 Jul 2016, at 8:06 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> On Wed, Jun 29, 2016 at 9:32 PM, Dean Jackson <[hidden email]> wrote:
>>> Secondly, we'd need to
>>> describe how this works for a keyframed animation, where the duration applies
>>> over all the keyframes.
>>
>> This, I think, is the part that needs the most thought.  This really
>> is a pretty big change from the current model, because it seems to be
>> impossible to accurately chain a spring effect into anything else
>> unless you run the math yourself to determine the effective duration.
>> That suggests pushing forward the timetable on "sequence/parallel
>> animation groups in WebAnim and CSS" might be worthwhile.
>
> Is it that important that spring() applies to keyframed animations
> from the beginning? Springs are an emulation of a physical effect, and
> it's rare that you'll combine that with a keyframe (which is an unnatural
> effect).
>
> Springs make more sense going between two points. e.g. transitions.
>
> I think we can address keyframes, but it isn't urgent. At worst we can
> leave it as is for now, which means that the keyframe would advance
> once its duration slice has expired. This could be while the animation
> is still springing, or well after it as settled.

I don't think it feels unusual to spring something into place, then
kick off some other animation when it arrives at the target spot.  You
can set up those types of things easily with keyframes and
duration-based timing functions.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Brad Kemper

> On Jul 1, 2016, at 2:44 PM, Brad Kemper <[hidden email]> wrote:
>
>
>
> For velocity, percentage per second makes a certain amount of sense to me, with it being a percentage of the distance between start and stop points. That "distance" could be along a color spectrum, for colors.

Percentage per second is a lousy unit for velocity. Velocity should by default be absolute so you don't have to multiply by the start-end delta to compare meaningfully to other velocities.

 - Maciej


Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Maciej Stachowiak
In reply to this post by Tab Atkins Jr.


(Alternate syntax: use units for these, like `spring(2mass
5velocity)`. Stronger connection between value and type, but also
maybe weird? Unsure.)

"mass" and "velocity" aren't units, they are types of units. This would be like writing "8length" instead of "8px".

Please don't make physicists cry.


(Second alternate syntax: finally invent "named arguments" for real,
like some people have been agitating for for a while.  `spring(mass:
2; velocity: 5;)`?  To be less weird we'd have then go and backport
this to other functions. Probably a decent idea? Need to noodle on
syntax more, look at several different functions that use syntax
differently.

That's a more appealing syntax and makes it easier to figure out defaults.


We could pick another formula that is more amenable to duration-based
springs.

However, there is some criticism against coding an animation like this
purely on duration:
https://medium.com/@flyosity/your-spring-animations-are-bad-and-it-s-probably-apple-s-fault-784932e51733

That criticism is geared towards a bad API design that required you to
specify a *technically redundant* duration, and if you didn't specify
what the algo would have "naturally" provided you get an
unnatural-looking result.

My read is that it actually solves the spring equation in reverse and computes a stiffness and mass for the given duration. There is no stiffness or mass provided to the API, just damping (as a ratio, presumably relative to stiffness or something) and initial velocity. So the duration is not redundant.

I think the reason the spring examples using the API look bad is that authors are likely to severely underestimate the duration required for a comfortable looking bounce, thus resulting in springs with crazy high stiffness which look awkward even though they are technically correct.

Regards,
Maciej


Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Tab Atkins Jr.
[I don't know what client you're using, but whatever they
On Fri, Jul 1, 2016 at 5:37 PM, Maciej Stachowiak <[hidden email]> wrote:
>> (Alternate syntax: use units for these, like `spring(2mass
>> 5velocity)`. Stronger connection between value and type, but also
>> maybe weird? Unsure.)
>
>
> "mass" and "velocity" aren't units, they are types of units. This would be
> like writing "8length" instead of "8px".
>
> Please don't make physicists cry.

But in this circumstance they're *families* of units - velocity might
be px/sec, or hue/sec, etc.  Classifying that as a generic unit
"velocity" doesn't seem *too* crazy to me. (That said, this is my
least favorite syntax possibility.)

>> (Second alternate syntax: finally invent "named arguments" for real,
>> like some people have been agitating for for a while.  `spring(mass:
>> 2; velocity: 5;)`?  To be less weird we'd have then go and backport
>> this to other functions. Probably a decent idea? Need to noodle on
>> syntax more, look at several different functions that use syntax
>> differently.
>
> That's a more appealing syntax and makes it easier to figure out defaults.

Kk. This is just the more formalized version of option 1 (just do
keyword/number pairs), and implies that we need to do the work of
porting it back to other functions and properties.

>>> We could pick another formula that is more amenable to duration-based
>>> springs.
>>>
>>> However, there is some criticism against coding an animation like this
>>> purely on duration:
>>> https://medium.com/@flyosity/your-spring-animations-are-bad-and-it-s-probably-apple-s-fault-784932e51733
>>
>> That criticism is geared towards a bad API design that required you to
>> specify a *technically redundant* duration, and if you didn't specify
>> what the algo would have "naturally" provided you get an
>> unnatural-looking result.
>
> My read is that it actually solves the spring equation in reverse and
> computes a stiffness and mass for the given duration. There is no stiffness
> or mass provided to the API, just damping (as a ratio, presumably relative
> to stiffness or something) and initial velocity. So the duration is not
> redundant.
>
> I think the reason the spring examples using the API look bad is that
> authors are likely to severely underestimate the duration required for a
> comfortable looking bounce, thus resulting in springs with crazy high
> stiffness which look awkward even though they are technically correct.

Ah, that might be right, I didn't dive deeply into the examples given.
If that's the case, then yeah, it implies that authors are just
generally terrible at figuring out durations properly, and we should
indeed avoid specifying them explicitly.

But that leans more on my other point, that this implies we should
work more on animation sequencing, which is currently deferred to v2
of WebAnim.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-transitions] Proposal and RFC: spring() timing function

Rachel Nabors
I'm very happy to see timing functions that allow for more than two bounces in a transition! I've been advocating for more complex timing functions for some time and am glad to see some movement on the topic!

However, a few issues:

1) With more and more designers building more and more complex motion in apps like After Effects looking for ways to export these effects to HTML5, there are currently no timing functions they can export their complex motion graphs to. This is a big problem that no one has been able to solve. Porting a mockup of an SVG animation from AfterEffects to HTML and CSS is a painful and complex process that involves a lot of eye-balling hacking together cubic-beziers into keyframe animations (to say nothing of how you cannot do such with transitions). I see a pressing need not just for a complex timing function to export to, but also...

2) ...and this is why I bring this need up here, a complex timing function could express functions like spring(), steps(), etc (and frames(), too, hopefully) and allow the creation of new, reliable timing functions in the future that build off its syntax under the hood. As to how this pertains to spring() and its cross-browser reliability, see this comment: https://github.com/w3c/csswg-drafts/issues/229#issuecomment-228260667

I've put up an issue for complex timing functions, and would love to see you all weigh in on it: https://github.com/w3c/csswg-drafts/issues/229



On Fri, Jul 1, 2016 at 5:51 PM Tab Atkins Jr. <[hidden email]> wrote:
[I don't know what client you're using, but whatever they
On Fri, Jul 1, 2016 at 5:37 PM, Maciej Stachowiak <[hidden email]> wrote:
>> (Alternate syntax: use units for these, like `spring(2mass
>> 5velocity)`. Stronger connection between value and type, but also
>> maybe weird? Unsure.)
>
>
> "mass" and "velocity" aren't units, they are types of units. This would be
> like writing "8length" instead of "8px".
>
> Please don't make physicists cry.

But in this circumstance they're *families* of units - velocity might
be px/sec, or hue/sec, etc.  Classifying that as a generic unit
"velocity" doesn't seem *too* crazy to me. (That said, this is my
least favorite syntax possibility.)

>> (Second alternate syntax: finally invent "named arguments" for real,
>> like some people have been agitating for for a while.  `spring(mass:
>> 2; velocity: 5;)`?  To be less weird we'd have then go and backport
>> this to other functions. Probably a decent idea? Need to noodle on
>> syntax more, look at several different functions that use syntax
>> differently.
>
> That's a more appealing syntax and makes it easier to figure out defaults.

Kk. This is just the more formalized version of option 1 (just do
keyword/number pairs), and implies that we need to do the work of
porting it back to other functions and properties.

>>> We could pick another formula that is more amenable to duration-based
>>> springs.
>>>
>>> However, there is some criticism against coding an animation like this
>>> purely on duration:
>>> https://medium.com/@flyosity/your-spring-animations-are-bad-and-it-s-probably-apple-s-fault-784932e51733
>>
>> That criticism is geared towards a bad API design that required you to
>> specify a *technically redundant* duration, and if you didn't specify
>> what the algo would have "naturally" provided you get an
>> unnatural-looking result.
>
> My read is that it actually solves the spring equation in reverse and
> computes a stiffness and mass for the given duration. There is no stiffness
> or mass provided to the API, just damping (as a ratio, presumably relative
> to stiffness or something) and initial velocity. So the duration is not
> redundant.
>
> I think the reason the spring examples using the API look bad is that
> authors are likely to severely underestimate the duration required for a
> comfortable looking bounce, thus resulting in springs with crazy high
> stiffness which look awkward even though they are technically correct.

Ah, that might be right, I didn't dive deeply into the examples given.
If that's the case, then yeah, it implies that authors are just
generally terrible at figuring out durations properly, and we should
indeed avoid specifying them explicitly.

But that leans more on my other point, that this implies we should
work more on animation sequencing, which is currently deferred to v2
of WebAnim.

~TJ

--
Curator of Web Animation Weekly
Speaking & Workshops
• Apr 05 –06 SmashingConf, San Francisco
• Apr 21 Frontend Masters, online, CSS Animations and Transitions Master Class
• May 18 –20 Front-Trends Keynote, Warsaw
• Jun 01 CSSconf Nordic, Oslo
12