-
Notifications
You must be signed in to change notification settings - Fork 686
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
Comments
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 While you could say this auto-finish behavior is fine for Practically, continuing with 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. (I also thought of maybe using
What about Along with |
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
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) |
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. |
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:
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 |
The is current property in web-animations captures the concept of animations on non-monotonic timelines which may still be animating. |
The CSS Working Group just discussed
The full IRC log of that discussion<TabAtkins> bramus: When the animations contained in a VT all reach the finished state, the VT itself also reaches finished, and goes away<TabAtkins> bramus: When implementing draggable VTs, or scroll-driven, there's a need to prevent that from happening. <TabAtkins> bramus: If you touch the screen and drag the animation, you hit the bottom it reaches 100%, but if you drag back up you still want it to reverse. <TabAtkins> bramus: So request is to prevent it from reaching that finished state <khush> q+ <TabAtkins> bramus: Proposal is to add a method on the VT object that prevents it from finishing. Propose .preventAutoFinish() <ydaniv> q+ <TabAtkins> bramus: But also a counterpart for allowAutoFinish(); if you lift your finger and it's finished you want to really finish it <astearns> ack khush <flackr> q+ <TabAtkins> khush: Two things to add. Similar cam efor scroll-driven, if you're doing something in a rAF loop the brwoser can't tell when you're done <TabAtkins> khush: the other is the API option I added on the issue is a new api called waitUntil() which takes a promise <TabAtkins> khush: lets you combine the browser figuring out when the animation is done and other things <ydaniv> q- <TabAtkins> khush: Also good because multiple parts can each call .waitUntil() and give their own promise, and it won't be done until they all settle <astearns> ack flackr <TabAtkins> flackr: for the animations case, WA has an .isCurrent concept for if the animation can continue to produce updates. we use that for .getAnimations() too, ,to return animations that are finished but can become active again <TabAtkins> flackr: so VT might want to use this instead of the strict "finished" concept <TabAtkins> flackr: but khushal pointed out ones driven entirey by the user. maybe do that with CustomEffect, called out in WA spec. A JS animation that's driven by a declarative aniamtion of some duration. <bramus> On the side: demo of a (hacked together) Scroll-Driven View Transition: https://codepen.io/bramus/pen/BabRVLg <TabAtkins> khush: I'm not sure about asking devs to use CustomEffect for something like this <TabAtkins> khush: right now they work around it by setting up an infinite declarative animation, and just call abort when they're done <TabAtkins> khush: there's a need for a pattern when they don't want or need anything declarative, doing it all in script, and just want an easy way to teell the browser when they're done <TabAtkins> flackr: I think you could do the similar thing with an infinite duration customeffect, and you just cancel that when you're done animating <bramus> q+ <TabAtkins> flackr: whether it's better is an open question, it just avoids the need for an additional api, which might be nice <TabAtkins> khush: right now in the spec we ignore animations unless they use tehe doucment timeline. this was because it was hard to reason about the scroll timeline not finishing, etc <TabAtkins> khush: now if the author overrides all animations with scroll timeline, is it possible for the browser to automatically identify when the animation is done? <TabAtkins> flackr: no, they'd be considered to be permanently active <astearns> ack bramus <TabAtkins> khush: the new api was meant to address that too <TabAtkins> bramus: wanted to mention animations using a non-document timeline <emilio> q+ <TabAtkins> bramus: right now the behavior is if you drag outside the specified range, the VT gets zapped, i want to prevent that <TabAtkins> flackr: .isCurrent "fixes" that, but it means we'd never be done with the VT <TabAtkins> bramus: which isn't something you want since while tehe VT is running the snapshots are inert <TabAtkins> khush: reading bramus's proposal, i don't mind the explicit finish call, but then you have to have in userland when all the animations are done <TabAtkins> khush: the waitUntil() proposal lets each point hook in their own promises so userland doesn't have to manage things <TabAtkins> bramus: so for a demo - i'd start on pointerdown, prevent it from autofinishing, then on pointerfinish unlock it again <ydaniv> q+ <astearns> ack emilio <TabAtkins> TabAtkins: You can just start a promise on pointerdown, resolve it on pointerup. then it's back under browse control <TabAtkins> emilio: I think I'd prefer a prevent - the non-promise version, because building the promise on top seems more trivial. easy to leak with promises. <TabAtkins> emilio: seems simpler that a bug is becuase someone didn't call .finish() versus tracking a never-resolved promise <TabAtkins> emilio: but no strong objection either way. just feels like providing the lower-level api is a little nicer, a little less footgunny <TabAtkins> flackr: devil's advocate, the one thing harder with the direct api is coordinating between libraries <TabAtkins> flackr: one library might say it's done and end it <TabAtkins> flackr: maybe not a strong reason, just pointing it out <astearns> ack ydaniv <TabAtkins> ydaniv: i'm concerned it might be risky to give any api and then everything can get stalled <TabAtkins> ydaniv: what if we default to if you reach 100% plus a scrollend was fired. would that be a reasonable default? <TabAtkins> bramus: I think that's specifically targeted to this one use-case for scrolling, there might be more. <TabAtkins> bramus: I'm also coming around more to the promises, there's a lot of promises on the web. <TabAtkins> khush: the demos we've seen involve taking raw touch events and mapping them to gestures without having a scroll container <TabAtkins> astearns: for my clarity, the promise-based is an alternative to the bare prevent/allowFinnish() calls <TabAtkins> astearns: is there a summary of the promise-based that could be added? <bramus> s/allowFinnish/allowFinish <khush> transition.waitUntil(promise) keeps transition from finishing until all promises passed to waitUntil settle <TabAtkins> (can be called multiple times to add promises to the list) <TabAtkins> astearns: do we want to resolve, or take it back to the issue? <flackr> q+ <TabAtkins> bramus: can we bikeshed the name? waitUntil() can be a little confusing... <TabAtkins> TabAtkins: waitUntil() is already used in Service Worker for exactly this purpose <astearns> ack flackr <TabAtkins> flackr: I was gonna have a minor complaint about adding complexity, but if there's precedent... <TabAtkins> emilio: I'm okay resolving on it. I think I'd rather build the simpler thing first, but not a super stron gopinion either way. <TabAtkins> astearns: If we do this, is there a possibility we'll add the lower-level one anyway <TabAtkins> TabAtkins: They can be layered either way - both can be built on top of the other <TabAtkins> astearns: so proposal is to add a .waitUntil(promise) that keeps the transition from settling until all of the promises settle. <TabAtkins> RESOLVED: Add .waitUntil() promise to the VT object, prevents VT from finishing until the promises settle |
A view transition is removed when all constituent animations are no longer running or paused. However, the spec only defines this for document timelines:
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 theViewTransition
object?The text was updated successfully, but these errors were encountered: