Mastering React Native Animations — A Simple Spring Animation for a Map Icon

Maria James
4 min readOct 10, 2023

--

Animations can greatly enhance the user experience of your React Native applications. They add a touch of interactivity and polish that can make your app feel more dynamic and engaging. In this blog, we’ll explore how to use React Native’s Animated library to create smooth animations, with a straightforward spring animation applied to a map icon.

Before diving into the code, let’s understand the three key components of this React Native animation: initialization, spring animation, and JSX implementation.

1. Initialisation

const animation = useMemo(() => new Animated.Value(10), []);
  • useMemo(() => ...): useMemo is a hook in React that memoizes (caches) the result of a function and returns it. It takes two arguments: a function and a dependency array.
  • () => new Animated.Value(10): This is the function that useMemo is memoizing. It creates a new instance of Animated.Value with an initial value of 10.
  • []: This is the dependency array. When an empty array is provided, it means that the memoized value (in this case, the animated value) will not change as long as the component is mounted. It effectively runs the memoized function (in this case, creating the animated value) only once when the component mounts.

2. The Spring Animation

Animated.spring(animation, {
toValue: 30,
duration: 2000,
friction: 1,
tension: 1,
useNativeDriver: true
}).start();

This line of code is responsible for setting up and starting the animation. It uses the Animated.spring method to create a spring-based animation.

  • animation: This is the animated value that the animation is applied to. In our case, it's an instance of Animated.Value that starts at 10.
  • { toValue: 30, duration: 2000, friction: 1, tension: 1, useNativeDriver: true }: These are the configuration options for the animation
  • toValue: This is the final value that the animated property (in this case, animation) will reach. In this code, it's set to 30, meaning the animation will transition from 10 to 30.
  • duration: This is the duration of the animation in milliseconds. Here, it's set to 2000 milliseconds (or 2 seconds).
  • friction: This controls how "loose" or "tight" the spring feels. A higher value will make the animation feel more damped. Here, it's set to 1.
  • tension: This controls how "stiff" the spring is. A higher value will make the animation feel more stiff. Here, it's set to 1.
  • useNativeDriver: This is a performance optimization. When set to true, the animation is offloaded to the native thread, which can result in smoother animations. It's generally recommended to set this to true.
  • .start(): This method actually starts the animation.

The animation is wrapped in a useEffect hook. It determines when the animation should start. The second argument [animation] is the dependency array. This means that whenever the value of animation changes, the effect (in this case, starting the animation) will be triggered.

Since animation is a dependency and it's only created once ( as it is inside a useMemo), this effect will run once when the component mounts. This ensures that the animation starts when the component is first rendered.

3. JSX implementation

 <Animated.View style={{ transform: [{ translateY: animation }] }}>
<Image
style={{ width: 150, height: 150 }}
source={require("../assets/map.png")}
/>
</Animated.View>

This is JSX code that renders an animated view. Let’s break down the important parts:

  • <Animated.View>: This is a special animated version of the View component provided by React Native. It's used for animating elements.
  • style={{ transform: [{ translateY: animation }] }}: This is setting the style of the Animated.View. The transform property is an array of transformations to be applied to the view. In this case, it's using the translateY transform.
  • translateY is a translation along the vertical axis. It moves the view up or down. The value is determined by the animation variable, which is an animated value.
  • animation is used here to drive the animation. As the value of animation changes (animated from 10 to 30), it will cause the view to smoothly transition from its initial position to the final position.

Complete code:

 const animation = useMemo(() => new Animated.Value(10), []);

useEffect(() => {
Animated.spring(animation, {
toValue: 30,
duration: 2000,
friction: 1,
tension: 1,
useNativeDriver: true
}).start();
}, [animation]);

return (
<Animated.View style={{ transform: [{ translateY: animation }] }}>
<Image
style={{ width: 150, height: 150 }}
source={require("../assets/map.png")}
/>
</Animated.View>
);

For a complete working example of the above code discussed, you can explore this sandbox. This sandbox contains the entire code, allowing you to see the animations in action and experiment with the parameters to further understand their effects.

link : https://codesandbox.io/s/optimistic-andras-36447p?file=/src/App.js

--

--