Re: [csswg-drafts] [css-transitions][css-animations] Complex timing functions

Cubic beziers aren't a bad choice for timing functions. They're very 
easy to evaluate (just a few additions and multiplications). Also, 
most animation tools use some form of cubic spline to specify 
animation paths, which can be converted into cubic bezier easings with
 good fidelity.

There are two problems with `cubic-bezier()` as it is currently 
specced, however:

1. You can't specify a spline of multiple segments
2. `cubic-bezier()` is abusing 2d parametric curves to specify 1d 
functions

The first issue can be addressed by, essentially, just adding more 
points to the cubic-bezier() syntax. I believe this has already been 
proposed in various forms.

The second issue is pretty significant, though, and deserves some 
unpacking. `cubic-bezier()` is specified as a _2d_ bezier, a 2d 
parametric curve. This has a lot of implications, including:

1. Without additional constraints, the resulting curve isn't 
guaranteed to have a singular y value for a given x and can't be used 
to define a mathematical function. This has been dealt with by 
restricting x to the range [0, 1], but that doesn't actually address 
the root (no pun) problem -- because a cube root is involved there are
 still two extra solutions in the complex plane.
2. As mentioned, implementors must solve cube roots to work backwards 
from x to the implicit t parameter, before they get to the normal (and
 much simpler/exact!) bezier calculation to evaluate the easing 
function.
3. Tool authors who want to do a direct conversion of cubic spline 
segments to cubic-bezier()s have no use at all for the extra 
dimension, but must clutter the output with decimal approximations of 
1/3 and 2/3.

The extra dimension isn't useful and makes life harder for 
implementors and tool authors alike. Ideally, instead of having to 
specify a two-dimensional curve like `cubic-bezier(0.33333, 0.4, 
0.66666, 0.6)`, we ought to have gotten _one-dimensional_ curves, e.g.
 `cubic-bezier(0.4, 0.6)`.
 
With one dimension, instead of having to work backwards from 
(normalized) time to an implicit t, the normalized time could be used 
directly as the input without having to solve cube roots first.

I guess if I were going to make a concrete proposal, I'd like to see 
syntax for specifying 1d bezier splines, in a format something like 
`cubic-spline(c, [c,t,c,]* c)` (where the cs and ts are numbers).

The first and last values are exactly like the control points in 
`cubic-bezier()`, except since we're only dealing with one dimension, 
the "control points" are specified by scalar values, rather than pairs
 of them.

Between those end "control values", you could have zero or more 
(control value, time, control value) triples representing intermediate
 knots with their adjacent control "points". The knot positions (the 
middle value of the triples) would have to be monotonically 
increasing, in the range (0, 1).

As a concrete example, let's take the following complex easing:

```
 @keyframes example {
     from {
         some-property: 100px;
         animation-timing-function: cubic-bezier(0.33333, 0.25, 
0.66666, 0.8);
     }
     50% {
         some-property: 75px;
         animation-timing-function: cubic-bezier(0.33333, 0.5, 
0.66666, 0.6);
     }
     to {
         some-property: 50px;
     }
 }
```
Given the aforementioned `cubic-spline()` function, you could define 
the same animation more simply as:

```
 @keyframes example {
     from {
         some-property: 100px;
         animation-timing-function: cubic-spline(0.125, 0.4,0.5,0.75, 
0.8);
     }
     to {
         some-property: 50px;
     }
 }
```

IMO this seems better for both export tooling and hand authoring.

One thing this proposal doesn't address are use cases where you want 
easings/animations with sudden jumps in them. (i.e. not C0 continuous)
 Having multiple intermediate CSS keyframes may still be a good answer
 for animations with discontinuities (rather than trying to define 
timing functions with discontinuities), though in order to do that 
there would need to be a mechanism to specify different incoming and 
outgoing property values for a CSS keyframe.

-- 
GitHub Notification of comment by visiblecode
Please view or discuss this issue at 
https://github.com/w3c/csswg-drafts/issues/229#issuecomment-228259642 
using your GitHub account

Received on Friday, 24 June 2016 05:12:19 UTC