framer / motion

Open source, production-ready animation and gesture library for React
https://framer.com/motion
MIT License
22.41k stars 740 forks source link

[BUG] Animation lag after updating from v10x to 11x #2582

Closed rnnyrk closed 2 weeks ago

rnnyrk commented 2 months ago

1. Read the FAQs 👇

2. Describe the bug

After updating to the latest framer motion the mask animation on mouse position is super laggy

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/p/devbox/framer-motion-animation-lag-g4nw4d

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Clone this repository https://github.com/olivierlarose/cursor-hover-mask/tree/main
  2. Install with included dependencies
  3. Animation works fine
  4. Update to latest Framer Motion version
  5. Start project
  6. Animation is super laggy

5. Expected behavior

Expect the animation to be smooth, as in v10

6. Video or screenshots

Bad behaviour v10 https://github.com/framer/motion/assets/4519142/991827e3-d109-47ee-90c5-53e8a211ddcb

Bad behaviour v11 https://github.com/framer/motion/assets/4519142/36038fb3-126c-49e9-8c03-28e9f46d3ee0

erengy commented 2 months ago

I'm having the same issue after updating from 11.0.8 to 11.0.18.

Looks like it was introduced in 11.0.11, since reverting to 11.0.10 works for me. Might be related to #2448.

rnnyrk commented 2 months ago

Can confirm I get the expected behaviour with 11.0.10 indeed @erengy

mattgperry commented 2 months ago

@rnnyrk Can you make the sandbox public please?

rnnyrk commented 2 months ago

@mattgperry Sorry wasn't aware it was private. Changed it and should be public now

mattgperry commented 2 months ago

Thanks!

mattgperry commented 2 months ago

Ah yeah I'll have to take a look. Preferably what you'd do here is something with motion values and avoid rerendering. But although not the most performant way to do this, it should still work visually. It's happening because we now defer resolving keyframes until the next animation frame. I'll have to have a play and figure out what to do in these situations, maybe an opt-out or something.

jakezubry commented 2 months ago

The same issue: Demo with a new version is laggy Demo with 10.14 version is more stable Also, if I just change the transition duration to 0, it updates everything without delays. Hope it helps

quentinlagache commented 3 weeks ago

Ah yeah I'll have to take a look. Preferably what you'd do here is something with motion values and avoid rerendering. But although not the most performant way to do this, it should still work visually. It's happening because we now defer resolving keyframes until the next animation frame. I'll have to have a play and figure out what to do in these situations, maybe an opt-out or something.

Any update on this topic @mattgperry ?

mattgperry commented 2 weeks ago

I'm going to have a look at this now. It might be that the per-frame render simply isn't fixed, I'll have to look into if that's possible (the perf increase of this within Framer > that pattern). But this approach https://codesandbox.io/p/sandbox/framer-motion-spring-transition-e6c8dm?file=%2Fsrc%2Fuse-follow-pointer.ts%3A23%2C1&from-embed= should work better than it currently is too. Annoyingly this one is very hard to write a good test around as it can be anywhere between very obvious and very subtle.

mattgperry commented 2 weeks ago

Unhelpfully:

mattgperry commented 2 weeks ago

https://github.com/framer/motion/assets/7850794/596140bc-7097-439d-9f9a-69c3f6fcc280

mattgperry commented 2 weeks ago

Oops. I had forced it back into sync mode, hence the better performance. Really strange about the performance recording though.

mattgperry commented 2 weeks ago

FYI I have a fix. It doesn't fix the use case of re-rendering once per animation frame, but as I originally said I am hesitant to address this. However it does make useSpring much more resilient to when and how often it is called - leading to smoother spring animations. I'll update our example to show the correct pattern once published.

mattgperry commented 2 weeks ago

Here's a version of your demo that uses useSpring to achieve a similar effect without re-rendering https://codesandbox.io/p/devbox/framer-motion-animation-lag-forked-wzp99c?file=%2Fsrc%2Fapp%2Fpage.js%3A15%2C28&workspaceId=a5b3421f-f215-4447-bd06-fd2db6cf83b4

Hopefully by tweaking the values you can get something similar to before.

erengy commented 2 weeks ago

Thanks for the demo, @mattgperry. I can confirm that after updating to 11.2.4, tracking the cursor with motion values and positioning the mask with useSpring and useTransform works for me.