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

Optimised appear animations V2 #2440

Merged
merged 17 commits into from
Dec 8, 2023
Merged

Optimised appear animations V2 #2440

merged 17 commits into from
Dec 8, 2023

Conversation

mattgperry
Copy link
Collaborator

@mattgperry mattgperry commented Dec 7, 2023

This PR changes the handoff strategy of optimised appear animations.

Before

Screenshot 2023-12-08 at 12 19 36

Currently, Framer runs hardware-accelerated opacity and transform animations via WAAPI before React hydrates. Then, when React hydrates, Framer Motion transfers opacity to a WAAPI animation and transform to the individual transform JS animations. This way, these animations can be interrupted independently via gestures etc as usual.

The problem with this approach is the precise timing required to seamlessly transfer WAAPI animations is difficult to get right and the accuracy of reported timings is different across browsers.

Therefore, on big pages animations can appear to jump and, once on the main thread, stutter, during this period of uniquely heavy JS initialisation.

After

This PR changes the strategy to preserve the optimised WAAPI animations for as long as possible.

Screenshot 2023-12-08 at 12 21 12

When we handoff, we start new JS animation for opacity and individual transforms, same as today. The difference is we don't cancel the WAAPI animations. WAAPI/CSS animations override any changes to an element's underlying computed styles so these JS animations aren't visible.

Only when a value needs to perform a different animation do we cancel the WAAPI animation. This way, we preserve the capability to interrupt transforms individually while also running an optimised animation for longer.

Screenshot 2023-12-08 at 12 22 24

Because all transforms are animating via JS, cancelling the WAAPI animation from any single transform will simply "reveal" the underlying animation, which is a tidy way of allowing any one transform to interrupt the unified transform animation.

In the majority of cases, the optimised animation will not be interrupted so we will now see an accelerated animation throughout the appear animation.

In the minority of cases where this animation is interrupted and we might have perceived a small jump or stutter, this will be improved because it is less noticeable to handoff to a different animation than an identical one.

@mattgperry mattgperry requested a review from shuangq December 7, 2023 15:54
Copy link
Contributor

@shuangq shuangq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some minor comments, but code LGTM! Nice solution & documentation 👏

* For synching handoff animations with the new Motion animation we want
* to ensure startTime is synchronously set.
*/
if (options.syncStart) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great that we can get rid of this! 🎉

Comment on lines +13 to +16
* Legacy arguments. This function is inlined as part of SSG so it can be there's
* a version mismatch between the main included Motion and the inlined script.
*
* Remove in early 2024.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inlined one in the script is startOptimizedAppearAnimation, right? Is this one also inlined? 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah both start and handoff get inlined - start actually applies this to window.HandoffAppearAnimation

@@ -118,6 +118,7 @@ export const animateMotionValue = (
* Animate via WAAPI if possible.
*/
if (
!transition.isHandoff &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a comment here to explain why we want to animate individual transforms when it's a handoff one.

@mattgperry mattgperry force-pushed the feature/optimised-appear-v2 branch from 5f827aa to e29abca Compare December 8, 2023 15:48
@mergetron mergetron bot merged commit d6565a3 into main Dec 8, 2023
1 check passed
@mergetron mergetron bot deleted the feature/optimised-appear-v2 branch December 8, 2023 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants