Open fantasai opened 2 years ago
The CSS Working Group just discussed transition delays in scroll-linked animations
.
It feels like adding transition
-related things to an animation timeline is trying to make it do too much, and makes it really hard to reason about what the duration and timing function really do.
Logically, it feels to me like the best approach is to allow authors to link "timeline modifiers" together in a list, where each modifier can alter the delay, rate and offset of the input progress, and output a new progress. This feels like it should be a new feature of the Web Animations API, rather than being bolted onto scroll timelines.
So to put it in more concrete terms, would the author create a new timeline which modifies an existing one? E.g. You might create something like a DelayedTimeline
which sourced another timeline:
element.animate(parallaxKeyframes, {
timeline: new DelayedTimeline(new ScrollTimeline(), {ease: 'ease'})
});
or in css:
#target {
animation: parallax delayed(scroll() 500ms ease);
}
Though I think the TLDR is that such an approach would be an improvement to animations support generally rather than part of scroll-animations-1. If so, should we close / repurpose this to be e.g. web-animations-2?
@smfr
makes it really hard to reason about what the duration and timing function really do.
That's not an issue here since in*-linked animations, as opposed to time-based animations, the duration is always 100%, and the delay is just an offset of the start. So, there's nothing to reason about here, it's just an extra interpolation between last value and the current one, described by a transition.
If it's not clear, I'll try to quickly create a demo.
Your suggestion for progress modifiers sounds like it's taking the same idea, but allowing authrs to provide a custom function for the easing. So might as well use cubic-bezier()
or linear()
now, or whatever we'll have next?
If it's not clear, I'll try to quickly create a demo.
FWIW I wrote a demo of this in the initial post (by setting a custom var to the scroll progress and applying a transition on it): https://jsbin.com/qekodug/edit?css,js,output
It is exactly as you say, a transition from the old scroll / time value to the new scroll / time value, the same as transitions work.
I'd like to take a shot at revisiting this issue, because this pattern is used quite often. I think we can take a different angle at this, by defining a friction factor to the interpolation on each frame between last and current positions, instead of having a transition with a defined duration on the animation, which is in fact the implicit way of calculating this factor.
Friction is actually 1 - playbackRate
, so for the default playbackRate=1
we get friction=0 and we get the default link between scroll and effect. For 0 < playbackRate < 1
we start getting friction>0 and the effect starts lagging behind the scroll progress in a sort of a transition and we get this drag. I think this is what @smfr was referring to above, and I think this might also simplify implementation.
The way the playbackRate
is used here is by interpolating on each frame from last position to current position using a simple lerp: a * (1 - t) + b * t
, where t
is the playbackRate
. So you can see how for t=0
the animation is paused, and we get default behavior for t=1
.
Applying easing on this effect is less common. Since the lerp already provides a nice curve, adding an extra easing on top is a bit redundant, but may be possible, I'm not quite sure yet whether this should be expressed in the interpolation function (i.e. instead of a simple lerp) or perhaps in some other way, modifying the progress that is calculated by it.
Still an open question, if we consider the above, is if/how we can expose a declarative syntax/API for this.
@flackr @birtles WDYT?
I read through the issue but I'm not sure I quite follow where / how the friction factor is applied or where the playbackRate
gets updated.
@birtles ok, here's a demo of what I mean: https://codepen.io/ydaniv/pen/VwBojoN
Now that I'm looking at it, I'm not sure I'm convinced myself, since the effect is sort of exponential in relation to the playbackRate
and not linear, so the effect starts being prominent only from about 0.1
and below.
@birtles @flackr @fantasai
I think this can still prove very useful for non-time-based timelines, this is a very common pattern used in the wild, adding a some lerp on the progress, which becomes just sync progress for playbackRate=1
.
I think it could make sense to consider it regardless of transition delays, as an effect that's tied to playbackRate
.
WDYT?
Copying out @flackr's comment https://github.com/w3c/csswg-drafts/issues/6674#issuecomment-945845884