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

[NativeAnimated][RN 0.34][iOS][Android] Misplaced animation frames while applying multiple transformations #10174

Closed
hubciorz opened this issue Sep 29, 2016 · 7 comments
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@hubciorz
Copy link

hubciorz commented Sep 29, 2016

Issue Description

When I'm running multiple transformations sometimes I see "missing frames" on random positions. Compare:
non-native(non-native driver)
native(native driver)

Steps to Reproduce / Code Snippets

I have created a repo here: https://github.com/hubciorz/react-native-heart-animation

git clone https://github.com/hubciorz/react-native-heart-animation
npm install
react-native run-ios

Every tap on a screen = one additional heart animation

This demo is based on http://browniefed.com/blog/react-native-periscope-hearts-animation/

(If you don't want to clone the repo, the animations-related code is available here: https://github.com/hubciorz/react-native-heart-animation/blob/master/heart-floater.js#L70-L132)

Expected Results

The animation should look the same as while using the "non-native driver"

Additional Information

  • React Native version: 0.34
  • Platform(s) (iOS, Android, or both?): iOS 10, real device (and probably 9.3), Android (but the reason seems to be different)
  • Operating System (macOS, Linux, or Windows?): macOS

It might be somehow connected with #9858

@raspasov
Copy link

While the native animation is running, do your views re-render by any chance? Specifically, the heart that blinks and looks janky?

I'm not quite sure, but I think I ran into the same issue and somehow got around it by ensuring that the view that's being "natively" animated is not re-rendered during the animation.

@hubciorz
Copy link
Author

@raspasov
No, I'm just adding a new heart every time I tap the screen.

  1. On "onPress" a new heart is added: https://github.com/hubciorz/react-native-heart-animation/blob/master/heart-floater.js#L145-L151
  2. Then the animation starts: https://github.com/hubciorz/react-native-heart-animation/blob/master/heart-floater.js#L105-L110
  3. ... and the heart transforms according to the rules defined here: https://github.com/hubciorz/react-native-heart-animation/blob/master/heart-floater.js#L78-L103

@raspasov
Copy link

@hubciorz just to verify, can you try to do a console.log in the render function of AnimatedHeart?

Without being 100% familiar with the React internals, I think I've seen a case where if you're passing a function as a prop, React always triggers a re-render of the children when the parent component re-renders, which is what is happening here I think.

@hubciorz
Copy link
Author

hubciorz commented Sep 29, 2016

@raspasov
My bad, it does re-render if the previous animation has not yet ended (I mean I tapped the screen while the previous animation was still playing). But why is it working with the non-native driver? And how to avoid that bug?

Anyway, thanks for that!

By the way, I have just run the example on Android and it looks even worse.

android

As you can see, it now renders some frames in completely different position (and sometimes angle) and the opacity works differently on Android. What's more, if I tap slowly on iOS (so the component does not re-render) the animation works fine (both drivers). This is not applicable on Android - it's broken anytime.

To sum up,
iOS non-native: works fine
iOS native: works fine only if I tap slowly and the previous animation has stopped playing
Android non-native: broken
Android native: I have no idea how to configure that

@hubciorz hubciorz changed the title [NativeAnimated][RN 0.34][iOS] Misplaced animation frames while applying multiple transformations [NativeAnimated][RN 0.34][iOS][Android] Misplaced animation frames while applying multiple transformations Sep 29, 2016
@raspasov
Copy link

@hubciorz As to why that is happening, someone who worked on the animated/native-animated module should chime in. My best guess is that when you set "useNativeDriver" true and you have a native animation + a JS re-render happening at the same time it gets hard for the library to keep track of where things are on the screen. My solution was for the component that's being animated to never be re-rendered while the native animation is running. In your case that would be each individual heart - once it's mounted there shouldn't be a reason for the JS thread to touch it. After it has faded away, you should wait till the native animation is finished "fading it" and then un-mount it via JS. I agree it's not the most intuitive when the behavior differs from the JS-driven animations. It took me a decent amount of time to intuitively develop this theory :). Still, I'm sure there's a lot of challenges/trade-offs that the people that worked on "useNativeDriver" had to consider.

In the cases where it got too weird or too hard to figure out why it's not working like the JS-based animation, I let it be and kept the JS-animations in place - in my experience they actually perform well for a variety of cases. The cases where you might run into problems are animations that have to be closely synchronized with a gesture on the screen - imagine two scroll views A and B, and scroll view A's position is driven by B's position and B is driven by a gesture from the user. In that case the slower your device/JS thread is, the more "discrepancy" (or lag) you might see between the two scroll views. Still, even this performs decently well for all but the 3+ year old devices.

PS My experience with React Native is only on iOS so far.

@thorbenandresen
Copy link

thorbenandresen commented Nov 30, 2016

In order fix the problem for iOS in this specific case, you have can place a shouldComponentUpdate = () => false in your AnimatedHeart Component.

However I currently struggle to work around this with other use cases like this one here. It would be really awesome to get this bug fixed.

@hramos
Copy link
Contributor

hramos commented Jul 20, 2017

Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!

If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:

  • Does the issue still reproduce on the latest release candidate? Post a comment with the version you tested.
  • If so, is there any information missing from the bug report? Post a comment with all the information required by the issue template.
  • Is there a pull request that addresses this issue? Post a comment with the PR number so we can follow up.

If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.

@hramos hramos closed this as completed Jul 20, 2017
@facebook facebook locked as resolved and limited conversation to collaborators Jul 20, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 20, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

7 participants