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

Using scale and rotate together sometimes ends up in an invisible component. #85

Closed
BrandonMA opened this issue Jul 6, 2021 · 19 comments · Fixed by #102
Closed

Using scale and rotate together sometimes ends up in an invisible component. #85

BrandonMA opened this issue Jul 6, 2021 · 19 comments · Fixed by #102

Comments

@BrandonMA
Copy link

BrandonMA commented Jul 6, 2021

What's happening?

Whenever you try to apply scale and rotate together the component sometimes renders and performs the animation, and sometimes it doesn't.

This is literally random as sometimes it works and sometimes it doesn't, I am not sure on how the library is implemented but might be some kind of race condition? I also include a video to show the problem plus the code to reproduce, it's literally me just pressing refresh many times.

Simulator.Screen.Recording.-.iPhone.8.-.2021-07-06.at.18.38.07.mp4

Code

import React from 'react';
import { View } from 'react-native';
import { MotiView } from 'moti';
import { registerRootComponent } from 'expo';

export function App(): JSX.Element {
    return (
        <View>
            <MotiView
                style={{ backgroundColor: 'blue', height: 300, width: 300 }}
                from={{ opacity: 0, scale: 0, rotate: '0deg' }}
                animate={{ opacity: 1, scale: 1, rotate: '45deg' }}
            />
        </View>
    );
}

export default registerRootComponent(App);

If you have an idea on why this is going on but don't have the time to fix it a brief explanation would be nice and I can make a pull request.

Snack

https://snack.expo.io/@brandonma/moti-rotate-scale-bug

@nandorojo
Copy link
Owner

Hmm very odd. What if you use a 0deg string instead of numbers for rotate?

It seems like #76 and #83 could be related, but I'm not totally sure why.

@nandorojo
Copy link
Owner

Random idea, does moving the props out of render make a difference? (Doubtful since there are no re-renders in your example)

What if you remove opacity? Do they still not work?

@nandorojo
Copy link
Owner

Does setting transition={{ type: 'timing' }} do anything? Maybe it's due to a mix of springs (the transforms) and timing (opacity), though I doubt it.

@nandorojo
Copy link
Owner

Could you put your reproduction on expo snack?

@BrandonMA
Copy link
Author

Does setting transition={{ type: 'timing' }} do anything? Maybe it's due to a mix of springs (the transforms) and timing (opacity), though I doubt it.

Setting timing for the transition type ends up in no animation in this particular scenario, if you remove scale it performs the animation😅

@BrandonMA
Copy link
Author

Hmm very odd. What if you use a 0deg string instead of numbers for rotate?

It seems like #76 and #83 could be related, but I'm not totally sure why.

Same effect if I use a string, no animation when using both properties, I will update the example and add it because it should have it.

@BrandonMA
Copy link
Author

BrandonMA commented Jul 7, 2021

Random idea, does moving the props out of render make a difference? (Doubtful since there are no re-renders in your example)

What if you remove opacity? Do they still not work?

Same😞 as you said there's no re renders but even if I take it out it keeps happening.

Actually removing opacity did the same as setting the transition to timing, the blue view appear instantly with the correct rotation and scale of 1, but no animation.

@BrandonMA
Copy link
Author

Could you put your reproduction on expo snack?

Yes for sure! I will add the snack to the issue once I finish it.

@nandorojo
Copy link
Owner

Hey just wanted to see if you were able to reproduce this in a snack. I'll close it for now, but more than happy to open it once it's reproduced! Thanks again.

@BrandonMA
Copy link
Author

Hey just wanted to see if you were able to reproduce this in a snack. I'll close it for now, but more than happy to open it once it's reproduced! Thanks again.

Actually it's already on the description! But here it is too: https://snack.expo.io/@brandonma/moti-rotate-scale-bug

@nandorojo nandorojo reopened this Jul 20, 2021
@nandorojo
Copy link
Owner

Ah thanks I missed that

@nandorojo
Copy link
Owner

Okay so this is interesting. It seems to work fine on Web, but I do see the issue on iOS sometimes...🧐

Here's a video of it working on Web: https://www.loom.com/share/7994f42ad2e54042ba73765506f7b88b

Snack: https://snack.expo.dev/@beatgig/moti-rotate-scale-bug

import * as React from 'react';
import { Text, View, Pressable } from 'react-native';
import { MotiView } from 'moti';

export default function App() {
  const [visible, toggle] = React.useReducer((visible) => !visible, true);
  return (
    <Pressable style={{ flex: 1 }} onPress={toggle}>
      {visible && (
        <MotiView
          style={{ backgroundColor: 'blue', height: 300, width: 300 }}
          from={{ scale: 0, rotate: '0deg' }}
          animate={{ scale: 1, rotate: '45deg' }}
        />
      )}
    </Pressable>
  );
}

@nandorojo
Copy link
Owner

nandorojo commented Aug 9, 2021

Temporary Solution

Use useAnimationState instead of the from & animate props.

Example

This works:

import * as React from 'react'
import { Text, View, Pressable } from 'react-native'
import { MotiView, useAnimationState } from 'moti'

const from = {
  scale: 0,
  rotate: '0deg'
}

const animate = {
  scale: 1,
  rotate: '45deg'
}

export default function App() {
  const state = useAnimationState({
    from,
    to: animate
  })

  return <MotiView style={{ backgroundColor: 'blue', height: 300, width: 300 }} state={state} />
}

Yet this does not work:

import * as React from 'react'
import { Text, View, Pressable } from 'react-native'
import { MotiView, useAnimationState } from 'moti'

const from = {
  scale: 0,
  rotate: '0deg'
}

const animate = {
  scale: 1,
  rotate: '45deg'
}

export default function App() {
  return <MotiView style={{ backgroundColor: 'green', height: 300, width: 300 }} animate={animate} from={from} />
}

I need to investigate why that is, but clearly there is some issue with the animate prop that isn't happening with the state prop. I don't exactly understand why. But could you try this solution and confirm that it works for multiple transforms?

Snack comparing the two here: https://snack.expo.dev/@beatgig/moti-rotate-scale-bug

Code:

import * as React from 'react'
import { Text, View, Pressable } from 'react-native'
import { MotiView, useAnimationState } from 'moti'

const from = {
  scale: 0,
  rotate: '0deg'
}

const animate = {
  scale: 1,
  rotate: '45deg'
}

export default function App() {
  const state = useAnimationState({
    from,
    to: animate
  })

  return (
    <Pressable style={{ flex: 1 }}>
      <MotiView style={{ backgroundColor: 'blue', height: 300, width: 300 }} state={state} />
      <MotiView style={{ backgroundColor: 'green', height: 300, width: 300 }} animate={animate} from={from} />
    </Pressable>
  )
}

@bennettfrazier

This comment has been minimized.

@nandorojo

This comment has been minimized.

@nandorojo
Copy link
Owner

I think I have an idea for what might be causing this. I'll investigate further after #100

@nandorojo
Copy link
Owner

Could you guys please test here and tell me if it's solved:

yarn add moti@presence

I changed up a bit how I resolve the from prop, wondering if that could be it.

@nandorojo
Copy link
Owner

I've found the solution, will push it there soon.

@nandorojo
Copy link
Owner

Fixed in 0.12.0

yarn add moti

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 a pull request may close this issue.

3 participants