Skip to main content

Working with Advanced Animations

1. Using Worklets

Example: Basic Worklet Usage

import { runOnJS } from 'react-native-reanimated';

function useWorklet() {
  const animatedValue = useSharedValue(0);

  const workletFunction = Worklets.createRunInContext(() => {
    'worklet';
    animatedValue.value = 100;
  });

  runOnJS(workletFunction)();
}

export default useWorklet;
Property Description Notes
Worklets.createRunInContext Creates a worklet function that runs in the UI thread Must be called with a function body wrapped in quotes
runOnJS Runs a function on the JavaScript thread Useful for updating state or calling JS-only functions

2. Creating Animated Reactions

Example: Basic Animated Reaction

import React from 'react';
import { Animated, TouchableOpacity } from 'react-native';

const AnimatedReaction = () => {
  const scale = new Animated.Value(1);

  const handlePress = () => {
    Animated.sequence([
      Animated.timing(scale, {
        toValue: 1.2,
        duration: 100,
        useNativeDriver: true,
      }),
      Animated.timing(scale, {
        toValue: 1,
        duration: 100,
        useNativeDriver: true,
      }),
    ]).start();
  };

  return (
    <TouchableOpacity onPress={handlePress}>
      <Animated.View
        style={{
          transform: [{ scale }],
        }}
      >
        <View style={{ width: 50, height: 50, backgroundColor: 'blue' }} />
      </Animated.View>
    </TouchableOpacity>
  );
};

export default AnimatedReaction;
Property Description Values
Animated.sequence Runs animations in sequence Array<Animated.Animation>
Animated.timing Animates a value over time { toValue: number, duration: number }
useNativeDriver Enables hardware acceleration true or false
Note: Always set useNativeDriver to true for better performance.
Warning: Ensure all animated values are initialized with new Animated.Value().

3. Interpolating Values

Property Description Values Notes
inputRange Array of input values that map to the output range [0, 1] Must be in ascending order
outputRange Array of output values that map to the input range [0, 100] Must have same length as inputRange
extrapolateLeft How to handle values below the input range 'extend', 'clamp', 'identity' Default is 'extend'
extrapolateRight How to handle values above the input range 'extend', 'clamp', 'identity' Default is 'extend'

Example: Basic Interpolation

import { interpolate } from 'react-native';\n\nconst value = new Animated.Value(0);\nconst interpolated = value.interpolate({\n  inputRange: [0, 1],\n  outputRange: [0, 100]\n});

Example: Color Interpolation

const color = animatedValue.interpolate({\n  inputRange: [0, 1],\n  outputRange: ['#ff0000', '#00ff00']\n});

4. Using Derived Values

Derived values in Expo animations allow you to create dynamic animations based on the values of other animated properties. They are particularly useful for creating complex animations that respond to user interactions or other animated values.

Property Description Usage
derivedValue Represents a value that is derived from another animated value.
const derivedValue = useDerivedValue(() => {
  return animatedValue.value * 2;
});
useDerivedValue Hook to create a derived animated value.
const derivedValue = useDerivedValue(() => {
  return animatedValue.value + 10;
});

Example: Using Derived Values for Scaling

import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';

const scaleValue = useDerivedValue(() => {
  return animatedValue.value * 1.5;
});

const animatedStyle = useAnimatedStyle(() => {
  return {
    transform: [{ scale: scaleValue.value }],
  };
});

Example: Combining Derived Values

import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';

const offsetX = useDerivedValue(() => {
  return animatedValue.value * 10;
});

const offsetY = useDerivedValue(() => {
  return animatedValue.value * 5;
});

const animatedStyle = useAnimatedStyle(() => {
  return {
    transform: [
      { translateX: offsetX.value },
      { translateY: offsetY.value },
    ],
  };
});
Note: Derived values are recalculated on every frame, so avoid heavy computations inside the derived value function to maintain performance.

5. Animating Colors

Property Values Description
color "#FF0000", "red", "rgb(255, 0, 0)" Color value to animate
duration 300 Animation duration in milliseconds
easing "ease-in-out" Easing function for animation

Example: Animating Color with Easing

import { Animated } from &#x27;react-native&#x27;;

const AnimatedColor = () => {
  const colorAnimation = new Animated.Value(0);

  Animated.loop(
    Animated.sequence([
      Animated.timing(colorAnimation, {
        toValue: 1,
        duration: 1000,
        easing: Animated.Easing.easeInOut,
      }),
      Animated.timing(colorAnimation, {
        toValue: 0,
        duration: 1000,
        easing: Animated.Easing.easeInOut,
      }),
    ])
  ).start();

  const backgroundColor = colorAnimation.interpolate({
    inputRange: [0, 1],
    outputRange: [&#x27;#FF0000&#x27;, &#x27;#00FF00&#x27;],
  });

  return (
    <Animated.View
      style={{
        width: 100,
        height: 100,
        backgroundColor,
      }}
    >
    </Animated.View>
  );
};

6. Creating Custom Easing

Easing Function Description Usage
Easing.functionName Predefined easing function from React Native Animated Animated.Easing.linear
Easing.custom Custom easing function using a cubic Bezier curve Easing.custom((t) => t * t)

Example: Custom Easing Function

import { Animated } from 'react-native';\n\nconst customEasing = (t) => {\n  return t * t;\n};\n\nconst animatedValue = new Animated.Value(0);\nAnimated.timing(animatedValue, {\n  toValue: 1,\n  duration: 1000,\n  easing: customEasing,\n}).start();
Note: Custom easing functions must return a value between 0 and 1 for any input between 0 and 1.

7. Using Animation Callbacks

Callback Type Description Usage Notes
onStart Called when the animation starts onStart={() => console.log('Animation started')} Useful for logging or triggering side effects
onEnd Called when the animation completes or is cancelled onEnd={(result) => console.log('Animation ended:', result.finished)} Result object includes finished boolean
onFrame Called on every animation frame (not recommended for heavy logic) onFrame={(frame) => console.log('Current frame:', frame)} Can be used for real-time updates or debugging

Example: Using Animation Callbacks

import Animated, { useAnimatedStyle, timing } from 'react-native-animated';

const AnimatedComponent = () => {
  const animation = useAnimatedStyle(() => {
    return {
      opacity: timing({ from: 0, to: 1 }),
      transform: [{ scale: timing({ from: 0.5, to: 1 }) }]
    };
  });

  return (
    <Animated.View
      style={animation}
      onAnimationStart={() => console.log('Animation started')}
      onAnimationEnd={(result) => {
        console.log('Animation ended:', result.finished);
      }}
    >
      <Text>Animated View</Text>
    </Animated.View>
  );
};
Note: Callbacks are not supported in all animation types. Ensure compatibility with the chosen animation method.

8. Implementing Spring Physics

Example: Basic Spring Configuration

import { useSpring } from 'react-native-reanimated';

const springConfig = {
  damping: 10,
  stiffness: 100,
  mass: 1,
  overshootClamping: false,
  restDisplacementThreshold: 0.01,
  restSpeedThreshold: 0.01,
};

const animatedValue = useSpring(0, springConfig);
Property Description Default Value Notes
damping How much to reduce the velocity by each frame 10 Higher values mean faster decay
stiffness How stiff the spring is 100 Higher values make the spring more rigid
mass Mass of the object being animated 1 Affects how quickly the spring responds
overshootClamping Whether to clamp the spring at its target position false Useful for preventing overshoot in UI elements
restDisplacementThreshold Threshold for considering the spring at rest 0.01 Used to stop animation when displacement is negligible
restSpeedThreshold Speed threshold for considering the spring at rest 0.01 Used to stop animation when velocity is negligible
Note: Spring physics in React Native Reanimated is based on the react-native-reanimated library and uses a physics engine to simulate realistic motion.
Warning: Incorrectly configured spring parameters can lead to jerky animations or infinite loops. Always test with realistic values.

9. Chaining Animations

Example: Basic Animation Chain

import { Animated } from 'react-native';\n\nconst AnimatedComponent = () => {\n  const animation = new Animated.Value(0);\n\n  const startAnimation = () => {\n    Animated.sequence([\n      Animated.timing(animation, {\n        toValue: 100,\n        duration: 500,\n        useNativeDriver: true\n      }),\n      Animated.timing(animation, {\n        toValue: 0,\n        duration: 500,\n        useNativeDriver: true\n      })\n    ]).start();\n  };\n\n  return (\n    <Animated.View\n      style={{\n        width: 100,\n        height: 100,\n        backgroundColor: 'blue',\n        transform: [\n          { translateX: animation }\n        ]\n      }}\n    />\n  );\n};
Animation Type Description Usage
Animated.sequence Runs animations in sequence Animated.sequence([anim1, anim2])
Animated.parallel Runs animations in parallel Animated.parallel([anim1, anim2])
Note: Use useNativeDriver: true for better performance.

10. Creating Repeating Animations

Property Description Values Notes
loop Controls whether the animation loops infinitely true / false Default is false
iterations Number of times the animation repeats number Set to -1 for infinite loop
direction Defines the direction of animation playback "normal", "reverse", "alternate" Default is "normal"

Example: Basic Looping Animation

import { Animated } from 'react-native';

const AnimatedComponent = () => {
  const animation = new Animated.Value(0);

  Animated.loop(
    Animated.timing(animation, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true
    })
  ).start();

  const rotate = animation.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg']
  });

  return (
    <Animated.View
      style={{
        transform: [{ rotate }]
      }}
    >
      <Text>Spinning Element</Text>
    </Animated.View>
  );
};

Example: Alternate Direction Animation

import { Animated } from 'react-native';

const AnimatedComponent = () => {
  const animation = new Animated.Value(0);

  Animated.loop(
    Animated.timing(animation, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true
    }),
    {
      iterations: 2,
      direction: 'alternate'
    }
  ).start();

  const scale = animation.interpolate({
    inputRange: [0, 1],
    outputRange: [1, 1.5]
  });

  return (
    <Animated.View
      style={{
        transform: [{ scale }]
      }}
    >
      <Text>Scaling Element</Text>
    </Animated.View>
  );
};

Was this article helpful?