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-view-transitions-1] How should scroll timeline animations be treated? #9901

Open
bokand opened this issue Feb 2, 2024 · 4 comments
Open
Labels
Agenda+ css-view-transitions-1 View Transitions; Bugs only

Comments

@bokand
Copy link
Contributor

bokand commented Feb 2, 2024

A view transition is removed when all constituent animations are no longer running or paused. However, the spec only defines this for document timelines:

  1. Let hasActiveAnimations be a boolean, initially false.
  2. For each element of transition’s transition root pseudo-element's inclusive descendants:
  3. For each animation whose timeline is a document timeline associated with document, and contains at least one associated effect whose effect target is element, set hasActiveAnimations to true if any of the following conditions is true:
    • animation’s play state is paused or running.
    • document’s pending animation event queue has any events associated with animation.

We should at least define what happens for other kinds of timelines.

However, as @bramus found it might be more useful to keep a view transition alive while it has a scroll timeline regardless of its current state, since it can be reversed by the user (unlike a document timeline). If we do that, I think authors can finish the view transition manually by calling cancel() on the transition animations? Perhaps we could make this more convenient via the ViewTransition object?

@bramus
Copy link
Contributor

bramus commented Feb 5, 2024

Thank you @bokand for filing this. Had this on my backlog to do :)

I did indeed find the need to prevent a View Transition from automatically finishing. This when using a non-monotonic timeline as the source of time progress that drives the animations – in my case a ScrollTimeline.

While you could say this auto-finish behavior is fine for ScrollTimeline in my specific demo – the VT should after all end at a certain point in time, it becomes more tricky when the timeline’s animation range is the full 100% or for things like a (currently spec-fictional) GestureTimeline.

Practically, continuing with GestureTimeline, I’m thinking of a situation where you want to drive a VT via a drag gesture over a dragdistance of 200px. When crossing the 200px boundary you don’t want the VT to finish immediately as the user – while still dragging – might change their mind and drag back to the 180px point. When doing so the same VT should then rewind a little bit, instead of creating a new one. Only on pointerup that VT should either snap back to its original state (when dragging back) or play to its end state (when dragging forward).

That to say: It depends on the type of timeline (ScrollTimeline, ViewTimeline, GestureTimeline, MediaPlaybackTimeline, …) and the use case.

So maybe this should be an opt-in, e.g. vtObject.preventAutoFinish() or document.startViewTransition({ callback, autofinish: false });?

(I also thought of maybe using vtObject.pause() instead of vtObject.preventAutoFinish() here but that doesn’t completely make sense here because you aren’t always pausing the VT’s animations)


I think authors can finish the view transition manually by calling cancel() on the transition animations?

What about vtObject.finish()? I choose finish() here because the vt would first play (forwards) and reach the finished state.


Along with vtObject.finish(), it would be nice here if there also were something like vtObject.revert() to have the animations play back to the start and then have the VT undo the DOM update. This for the situation where one starts dragging in one direction but then changes their mind and drags a little bit back in the opposite direction.

@bokand
Copy link
Contributor Author

bokand commented Feb 5, 2024

What about vtObject.finish()? I choose finish() here because the vt would first play (forwards) and reach the finished state.

Yeah, if we had some manual control on the vtObject that might make sense. I was considering the case where we just make it manual by default (in the case of a non-monotonic timeline). In that scenario, calling animation.finish wouldn't work since the VT no longer ends when the animations are finished; you'd have to use animation.cancel. But I suppose we could also add a vtObject.finish for that case as well...

Along with vtObject.finish(), it would be nice here if there also were something like vtObject.revert() to have the animations play back to the start and then have the VT undo the DOM update.

The hard part is undoing the DOM update - I don't think it's feasible to undo the update automatically; the author would have to pass in an "undo" callback. If this is common enough though it might be a nice ergonomic improvement (the author can already do all this themselves today)

@bramus
Copy link
Contributor

bramus commented Feb 5, 2024

the author would have to pass in an "undo" callback. If this is common enough though it might be a nice ergonomic improvement

This is effectively what I did in the gesture demo. When the VT has finished but it turned out to be a no-op (i.e. the animations reverted to the old state), I execute some logic to undo the DOM update.

@fantasai fantasai added the css-view-transitions-1 View Transitions; Bugs only label Feb 5, 2024
@khushalsagar
Copy link
Member

The idea of a VT not automatically finishing SGTM. We already had a use-case for this with rAF driven animations in #8132 and its trivial to implement. There's an alternate API suggestion there which does both: indicate that the transition shouldn't automatically finish and a promise to listen to for finishing it.

With the above, I'm assuming we wouldn't need to change anything about our logic for how "auto finish" works. Both conditions need to happen for a transition to finish:

  1. All animations with a monotonic animation timeline, which IIUC is limited to document timeline, have to finish.
  2. If there are any waitUntil promises, they have to settle.

I think 2) also helps with: "The hard part is undoing the DOM update". If the transition needs to be aborted, the author plays the animation in reverse. Now the DOM is only showing ::view-transition-old snapshots. The author updates the DOM and resolves the waitUntil promises. The DOM state should match the old snapshots being displayed so flip from VT pseudo-DOM to live old DOM is seamless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Agenda+ css-view-transitions-1 View Transitions; Bugs only
Projects
Status: Thursday afternoon
Development

No branches or pull requests

4 participants