Animations in

React Native

Niya Panamdanam

twitter: @findniya

findniya.com

gethealthie.com
gethealthie.com

 React JS   to   React Native 

Can You Add some Animations?

React Native has it's own language for movement

decay()

interpolate

clamp

useNativeThread

extrapolate

Performance

Declaritive vs Imperative

Libraries

- React Native Reanimated

- React Native Animatable

- React Native Shared Elements

- Popmotions

- React Spring

- React Motion

- Animated API

- Layout Animations

Built In

What Actually Happens When You Animate?

The

Animated

API

UI Thread

JS Thread

Native Thread

BRIDGE

UI | kicks of the request for the animation to the JS Thread

JS Thread

Native Thread

BRIDGE

JS Thread

Native Thread

BRIDGE

UI Thread

UI Thread

UI Thread

JS Thread

Native Thread

BRIDGE

UI Thread

JS Thread

Native Thread

BRIDGE

JS| animation driver uses requestAnimationFrame to execute on every frame.

JS| intermediate values are calculated and passed to View component.

JS| View is updated using setNativeProps

JS| talks to the Native bridge

UI Thread

JS Thread

Native Thread

BRIDGE

UI Thread

JS Thread

Native Thread

BRIDGE

Native | updates the UI Thread

A Busy JS Thread

Cause Frame Drops

Frame drops are not a great user experience.

Performance

useNativeDriver

- This moves all the JS Thread steps to the Native Thread.

UI Thread

JS Thread

Native Thread

BRIDGE

- Animated API produces a graph of animated nodes, which are all sent once to the Native Thread.

- Now the Native Thread can directly update the UI Thread and skip the JS Thread in between.

Interpolation

Interpolation is a type of estimation, a method of finding new data points based on the range of a discrete set of known data points.

f(x)

0

100

?

https://www.youtube.com/watch?v=ybcL8e6ImSo&ab_channel=eveningkid

Interpolate Opacity

translationX 0 to 100

opacity 0 to 1

x

f(x)

0

100

0

1

50

?

Animated Api

const Loader = () => {
    const translation = new Animated.Value(0)

    // animating image
    Animated.loop(
        Animated.timing(
            translation,
            {
                toValue: 100,
                duration: 3000,
                useNativeDriver: true
            }
        )
    ).start()

   
    return (
        <View style={styles.container}>
                <Animated.Image
                    style={{
                    transform: [{translateX: translation}],
                    opacity: translation.interpolate({
                      inputRange: [0, 100],
                      outputRange: [0, 1]
                      })
                    }}
                    source={require('../../assets/images/cookie.png')}
                />
        </View>
    )
}

Extrapolation & Clamp

translation 0 to 100

opacity 0 to 1

Start to change opacity

when translation = 25

and end when translation = 75

 

25

75

50

translation

0

100

inputRange

outputRange

-

-

-

0

1

0.5

Extrapolation & Clamp

0

0

1

1

Clamp the left and right ranges

Animated Api

return (
        <View style={styles.container}>
                <Animated.Image
                    style={{...styles.image, 
                    transform: [{translateX: translation}],
                    opacity: translation.interpolate({
                      inputRange: [25, 75],
                      outputRange: [0, 1]
                      
                      //******ADD CLAMP****
                      
                      extrapolate: 'clamp'
                      
                      //*****
                      })
                    }}
                    source={require('../../assets/images/cookie.png')}
                />
        </View>
    )


There Are Limitations

The libraries

  • React Spring: https://react-spring.io/

  • Moti: https://moti.fyi/

    • Reanimated (v2): https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation

React Spring

- A physics-based animation library

- It is build on Animated and React Motion.

- Brought in the abilities of Animated and added spring motion and declarative methods of React Motion

- It works in web and mobile.

React Spring

const AnimatedView = animated(View)

const Loader = () => {
    const springImage = useSpring({
        from: {rotate: "0deg"},
        to: {rotate: "360deg"},
        loop: true,
        config: {mass: 0.5, tension: 200, friction: 100},
    })
    
    return (
        <View style={styles.container}>
            <AnimatedView style={{...springImage, transform: [{rotate: springImage.rotate}]}}>
                <Image
                    style={styles.image}
                    source={require('../../assets/images/cookie.png')}
                />
            </AnimatedView>
        </View>
    )
}

Moti

UI Thread

JS Thread

Native Thread

BRIDGE

UI Thread

JS Thread

Native Thread

BRIDGE

- Built on Reanimated v2.

Abstracts the hooks to components that take an object.

JS Context

- Then adds more on top...

Combines the best of Framer Motion, React Spring and other libraries.

- Mobile/ React Native first, but also works on other platforms.

Moti

const Loader = () => {
    return (
        <View style={styles.container}>
            <MotiImage
                from={{
                    transform:[
                        {rotate: "0deg"}
                    ]
                }}
                animate={{
                    transform:[
                        {rotate: '360deg'}
                    ]
                }}
                transition={{
                    type: 'timing',
                    loop: true,
                    repeatReverse: false,
                    duration: 3000,
                }}
                style={styles.image}
                source={require('../../assets/images/cookie.png')}
            />
        </View>
    )
}

Reanimated v2

const Loader: React.FC = () => {

    const rotation = useSharedValue(0)

    const animatedStyle = useAnimatedStyle(() => {
        rotation.value = withRepeat(withTiming(360), 100, false)
        return {
            transform: [{rotate: `${rotation.value}deg`}]
        }
    }, [])

    return (
        <View style={styles.container}>
            <Animated.View style={animatedStyle}>
                <Image
                    style={styles.image}
                    source={require('../../assets/images/cookie.png')}
                />
            </Animated.View>
            <LoaderText/>
        </View>
    )
}

Let's Look At Some Live Example

Thank You