-
Notifications
You must be signed in to change notification settings - Fork 595
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
animations #487
Comments
Quick brainstorming: I think animations are awesome, so good to read this. Also think that route transitions should be treated completly different to component transitions, I see two groups there. I'm not clear why is needed a finite state machine. I guess that a priority queue would be enough to define animations order, a global one for route transitions, and one per each component. Also guessing here haha. See also |
In the example you start the animation by adding a CSS class, this way the animation state lives inside the css execution engine which makes it difficult to synch with re renders. This won't happen with style properties that are set from the component state. Re render won't be a problem because each time the component gets rendered the interpolated property value will be set so pausing/resuming will be possible. Similar to what react-motion does, the animation layer can handle timing and interpolation and pass the values that will be updated by nanomorph. (Not sure if this makes any sense for the choo architecture) |
@hugozap There are the transitionend and the animationend events to interact with the css animations. In fact, I think it is a MUST to handle those. |
Hey, just two things to mention:
|
@YerkoPalma Does this means that additional DOM mutations have to be disabled while the animation ends to avoid issues with re render? This is a big constraint (with css based animations). |
Thanks so much for all the links so far! - Feel like I haven't considered a bunch of things (e.g. aborting animations and going back) - so reading through all the links you've linked so far and figuring out how to do these things haha. Also had no idea about those DOM APIs - it'll take a lil while to work through it though I think haha. Will keep iterating on the main post to include the stuff y'all have been linking! |
@hugozap More than disabled, I think paused is the word, and in some case, some animations could cancel/disable other DOM mutations (i.e. route transitions should cancel component mutation IMO) |
@YerkoPalma For me the issue with CSS based animations is that things get complicated (or just not possible) for complex escenarios (staggering, composition, speed changes) , this in part is due to the animation information (e.g timing, easing) being hardcoded in the CSS declaration and not as part of the app state. I'm in favor of treating animation parameters like any other UI state data, so the same data flow ( state -> view ) can be maintained. With a non-css based approach to animate something just make sure to update the state as you wish and the animation layer will interpolate values that can be passed to modify the style attribute. |
In fact you can manipulate css animations from javascript, so you could include them in the app state, but, IMO, things can get a litle hacky from here. Links
|
PS if anyone's experimenting with any of this it'd be super cool if you posted back into this thread. Got a feeling that we can get this done soonish if we share notes :D |
Oh by the way, updates!
|
Been thinking about how to do animations a lil, and think having a component with Nanomorph would be the right place to add them. We should be able to do stuff like this at 60fps:
This is my current state of thinking; I'm not entirely sure how to approach this yet but I think laying out the constraints can help us with figuring out how to approach this. Apologies if I'm rambling a lil here, figured it'd be better to share notes & thoughts in the open, even if they're not as polished as they could be.
Constraints
There's a few things I think would be cool if we could pull off:
Component lifecycle events
Nanomorph takes care pretty well of rendering things on a screen. If you want to add an element, it'll take care of it with little trouble. However, it can't pause element mutation, which is crucial for animations. For example, say an element has a fade-in effect when it's first rendered. If we re-render midway through the animation it'll look weird. So we want to make sure the animation completes before any further mutations occur. Stuff like a fade-out before a component is removed isn't even possible right now, so we should allow for that.
Types of events
There's generally 3 types of events that happen¹:
Each of these events should be handed a lock that can be cleared using a callback. E.g. somewhat similar to:
While an animation is in progress, other animations and Nanomorph mutations should be put on hold.
The leave event
Because we just diff DOM nodes and don't do extra lifecycle tricks, we can't prevent elements from being unmounted. This means we can't trigger any animation when an element is removed from the DOM. To counter this we could, however, leave an element in the DOM that can instrument between its child elements and trigger hooks on each of them.
I think the approach might be to have some form of scheduler live in the DOM, that doesn't get unmounted so it can have its own Nanomorph instance. It can then do fine grained scheduling for its child elements, exposing all sorts of events².
Instrumenting Nanomorph through locks
As mentioned above, we would hand animation handlers a lock which they can free at the end of an animation. This is so we can make sure animations complete and don't conflict. E.g. imagine this scenario:
In this case we'd want the "enter" animation to complete, and only then mark the element to be removed from the DOM. Now, we can't immediately unmount the element - we need the animation to complete first. So we need a way to prevent the element from being removed.
Maintaining 60fps
ideally we'd be able to schedule the animations to the best of our abilities. E.g. not smush them all together in the same frame - but perhaps even better: schedule them when there's free time available. Something interesting to experiment be would be to find a midway: try and run the animation with
window.requestIdleCallback()
but run it anyway if it takes longer than 10ms or something. If every component would employ something like this, then things should run relatively smoothly (is my guess). Worth experimenting with at least haha.Instrumentation
So far we've only talked about how to allow transitions to work with nanomorph. Sometimes we'll need to instrument full page animations³. In react-f1 there's a distinction between individual element renders, and full page instrumentation. Another good example of this would be jam3.com.
The way
f1
/react-f1
does it is by declaring a finite state machine, and using a pathfinding algorithm to navigate between the nodes. If you do several layers of this, you can create pretty wild animations. An example of a pathfinding algorithm is jkstra for Dijkstra / A* pathfinding.Unanswered questions
A tricky thing with Nanomorph is that we can't have multiple
on-load
handlers on any given node so we're slightly constrained in that regard. But there's a few more things I think we should try to figure out:Wrapping up
I hope this somewhat explains the constraints my thoughts on the matter, and helps start a discussion on how to best approach animations. Thanks heaps for making it this far, and keen to hear your thoughts!
See Also
edit: meant nanomorph, not morphdom haha
The text was updated successfully, but these errors were encountered: