DEV Community

Abdelhalim Ahmed
Abdelhalim Ahmed

Posted on

How Moti is the shortest way to create universal animation based on reanimated 2

Today I would like to share my experience with Moti animation and create a Wave indicator using reanimated 2 and Moti.
final code: https://snack.expo.dev/@abdelhalimahmed/live-wave-animation

Image description

Let's start

What's the Moti?
Briefly, it helps you create universal animations "works on all platforms" in a much simpler way, powered by Reanimated 2, for more details check references on the bottom.


Situation:

In my current job, I got a task with a little animation like the above demo and I was thinking what's the easiest way to do it, actually, my first glance is creating it using Lottie, but I said why? let's do it with Reanimated 2 which it's my favorite performant animation library in the meantime.

hint: I used styled-components, but you can use any preferred UI library

1- I created a static dot component with fixed height and width with half border-radius "Circle"

const Dot = styled.View'
width: 20px;
height: 20px;
border-radius: 10px;
background-color: green;
';

2- Add array with length 3 which contain Animated view waves with the same style of Dot and positioning 'absolute'

const Wave = styled(Animated.View)'
width: 20px;
height: 20px;
border-radius: 10px;
background-color: green;
';
{Array.from({ length: 3 }, (_, i) => (
<Wave
style={StyleSheet.absoluteFillObject}
key={i} />
))};

3- Animation Part: 
 - Create animation value using "useSharedValue" that's contains the init value of "0" and will be "1" after triggering the animation. 
 - Animation style using "useAnimationStyle" that's contain the scaling value and opacity value with "interpolate" to map [0,1] to target value based on animation "scale | opacity" for example the scaling will be from "1x" -> "5x" so we will "interpolate" the animation value from [0,1] -> [1,5] …etc
 - trigger the animation inside "useEffect".

const animationValue = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{
scale: interpolate(animationValue.value, [0, 1], [1, 5])
}],
opacity: interpolate(animationValue.value, [0, 1], [0.7, 0]),
};
});
useEffect(() => {
animationValue.value =
withDelay(
index * 400,
withRepeat(
withTiming(
1,
{ duration: 2000, easing: Easing.out(Easing.ease) }
),
-1,
false
)
);
}, [index, animationValue]);
<Wave
style={[StyleSheet.absoluteFillObject, animatedStyle]}
key={index} />

That's IT 🔥🥳
But one Second!, where is the Moti Here?

Okay, After I finished the task and when streaming youtube I found Catalin Miron "who's building awesome animation using react native, I recommend checking his channel" released a new video very close to my animation challenge but he used the Motie!, so I mapped his code to fit my challenge and the result is awesome! with a few lines of my code!.
so with easily, the wave view comes from Moti components with animations properties like "from" that's mean the start point of the animation view, "animate" that's the endpoint animation is done, "transition" the type and options for animation you want.

import {View} from '@motify/components';
const Wave = styled(View)'
width: 20px;
height: 20px;
border-radius: 10px;
background-color: green;
';
<Wave
key={index}
from={{opacity: 0.7, scale: 1}}
animate={{opacity: 0, scale: 5}}
transition={{
type: 'timing',
duration: 2000,
easing: Easing.out(Easing.ease),
delay: index * 400,
loop: true,
repeatReverse: false
}}
style={[StyleSheet.absoluteFillObject]} />

References 📚

https://www.youtube.com/watch?v=XkoFvsscsHo
https://www.youtube.com/channel/UCTcH04SRuyedaSuuQVeAcdg
https://moti.fyi/
https://docs.swmansion.com/react-native-reanimated/docs/

Did you like it? Clap, and Follow! 👏

if you see something wrong or have an improvement please leave a comment and surely if you need a help with your React Native app feel free to contact me ;), I will be happy to discuss it.

Top comments (1)

Collapse
 
staunchcfo profile image
Emeka Okezie

Hello Abdelhalim Ahmed, I am having some issues with animating my React Native application, using Moti.

I keep have my animation state initialised like this:

const animationState = useAnimationState({
signIn: {
height: SIZES.height * 0.55
},
signUp: {
height: SIZES.height * 0.7
}
});

But I keep getting the error in the screenshot attached to this post.
Image description

Is there anything you can suggest I do please.