nandorojo / moti

🐼 The React Native (+ Web) animation library, powered by Reanimated 3.
https://moti.fyi
MIT License
4.07k stars 130 forks source link

Moti Interpolation based on Progress value of a Drawer #125

Closed KJ-GM closed 2 years ago

KJ-GM commented 2 years ago

I want to ask if it's possible to implement this code of reanimated using Moti.

Code with Reanimated 2:

// Drawer Animation progress const progress = useDrawerProgress();

// Animations - borderRadius const borderRadius = interpolateNode(progress, { inputRange: [0, 1], outputRange: [0, 26], Extrapolate: Extrapolate.CLAMP, });

// Combined Animation const animatedStyle = { borderRadius };

// Return function

{screen}
nandorojo commented 2 years ago

This looks like reanimated v1 code. Moti is compatible with any reanimated v2 code. However, in this case, I'm not entirely sure what you're trying to achieve with moti.

KJ-GM commented 2 years ago

This looks like reanimated v1 code. Moti is compatible with any reanimated v2 code. However, in this case, I'm not entirely sure what you're trying to achieve with moti.

First of all, thank you for quick response, So the aim of this Animation is basically to animate the screens when the drawer opens from the left, the animation is animated according the progress value of the drawer opening. In this case the animation is for border radius.

nandorojo commented 2 years ago

Yeah, but I don't see why this is related to Moti. You aren't even using Moti in the code, just Reanimated. If you were using v2, you'd need to use useAnimatedStyle and interpolate, but I don't see that in your code, so I assume you're using v1.

KJ-GM commented 2 years ago

interpolate

Yes I know it is not with Moti, I recently integrated Moti and I am trying to achive what I explained above, I was able to do it with reanimated v1. Is it possible to use Moti to animate a screen view according to the react navigation drawer progress value ?

nandorojo commented 2 years ago

Yeah you can use pass useDerivedValue to the animate prop

KJ-GM commented 2 years ago

Yes, I have seen the document about useInterpolateMotiPressable which mentions useDerivedValue, I am really new to the animation world of react native, so if you could please show me how the code would like with Moti that would be very appreciated.

nandorojo commented 2 years ago

With Reanimated 2:

import Animated, { interpolate, useAnimatedStyle } from 'react-native-reanimated'

const Screen = () => {
  const progress = useDrawerProgress()

  const animatedStyle = useAnimatedStyle(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <Animated.View style={animatedStyle}>{screen}</Animated.View>
}

With Moti's animate prop:

import { interpolate, useDerivedValue } from 'react-native-reanimated'
import { MotiView } from 'moti'

const Screen = () => {
  const progress = useDrawerProgress()

  const animate = useDerivedValue(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <MotiView animate={animate}>{screen}</MotiView>
}

Note that Moti's animate prop may not be what you want here, since it will automatically apply animations for you. To customize them, use the transition prop.

Bonus

A MotiView can receive any props that an Animated.View can. The code below is the same as the first example, except that it uses MotiView instead of Animated.View.

import { interpolate, useAnimatedStyle } from 'react-native-reanimated'
import { MotiView } from 'moti'

const Screen = () => {
  const progress = useDrawerProgress()

  const animatedStyle = useAnimatedStyle(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <MotiView style={animatedStyle}>{screen}</MotiView>
}

Note

Be sure that your drawer does not have useLegacyImplementation={true}: https://reactnavigation.org/docs/drawer-navigator/#uselegacyimplementation

KJ-GM commented 2 years ago

With Reanimated 2:

import Animated, { interpolate, useAnimatedStyle } from 'react-native-reanimated'

const Screen = () => {
  const progress = useDrawerProgress()

  const animatedStyle = useAnimatedStyle(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <Animated.View style={animatedStyle}>{screen}</Animated.View>
}

With Moti's animate prop:

import { interpolate, useDerivedValue } from 'react-native-reanimated'
import { MotiView } from 'moti'

const Screen = () => {
  const progress = useDrawerProgress()

  const animate = useDerivedValue(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <MotiView animate={animate}>{screen}</MotiView>
}

Note that Moti's animate prop may not be what you want here, since it will automatically apply animations for you. To customize them, use the transition prop.

Bonus

A MotiView can receive any props that an Animated.View can. The code below is the same as the first example, except that it uses MotiView instead of Animated.View.

import { interpolate, useAnimatedStyle } from 'react-native-reanimated'
import { MotiView } from 'moti'

const Screen = () => {
  const progress = useDrawerProgress()

  const animatedStyle = useAnimatedStyle(() => ({
    borderRadius: interpolate(progress, {
      inputRange: [0, 1],
      outputRange: [0, 26],
      Extrapolate: Extrapolate.CLAMP
    })
  }))

  return <MotiView style={animatedStyle}>{screen}</MotiView>
}

Note

Be sure that your drawer does not have useLegacyImplementation={true}: https://reactnavigation.org/docs/drawer-navigator/#uselegacyimplementation

Wow! Thank you so much; your efforts are greatly appreciated!

nandorojo commented 2 years ago

Happy to help. Feel free to check out my other libraries too, if you're new to React Native.

If you find any of them useful, it helps if you can tweet it: https://twitter.com/fernandotherojo

KJ-GM commented 2 years ago

Happy to help. Feel free to check out my other libraries too, if you're new to React Native.

If you find any of them useful, it helps if you can tweet it: https://twitter.com/fernandotherojo

Yes for sure 👍, So after implementing the code above with Moti or Reanimated 2, there is an error that pops up saying TypeError: No default value it comes from interpolation.ts(129:7) I am not sure how can this be solved, is it a bug or something is missing here ?

Notice: useLegacyImplementation is set to false as you told me. useLegacyImplementation={false}.

Here is a picture of it:

e2495c65-dd1e-441a-8dbb-b536e0b73d06

KJ-GM commented 2 years ago

Happy to help. Feel free to check out my other libraries too, if you're new to React Native. If you find any of them useful, it helps if you can tweet it: https://twitter.com/fernandotherojo

Yes for sure 👍, So after implementing the code above with Moti or Reanimated 2, there is an error that pops up saying TypeError: No default value it comes from interpolation.ts(129:7) I am not sure how can this be solved, is it a bug or something is missing here ?

Notice: useLegacyImplementation is set to false as you told me. useLegacyImplementation={false}.

Here is a picture of it:

e2495c65-dd1e-441a-8dbb-b536e0b73d06

Alright, so I found the issue, and it appears to be in how we pass the progress param value for the interpolation function in Reanimated v2 differs from Reanimated v1. This case can be closed now. I would like to thank again Fernando for his powerful libraries, and wish him all the best.

nandorojo commented 2 years ago

I assume we just forgot to do progress.value?