Simple animation
You'll learn to make the jump smooth with React Native's Animated: a value that moves from one number to another over time.
Watch & read
Start with the required ones. The others are there when you need them.
Explanation
Right now the square teleports: one tap and it is at the top. Real things do not move like that. A cricket ball rises, slows down, and then comes back down.
Think of a lift in a building. You press 5, and the lift does not appear at floor 5. It passes 2, 3 and
4 on the way. Animated is like that: you say where to go and how long to take, and it fills in all
the numbers in between.
An Animated.Value is a number that Animated can move. Keep it in useRef, so the same value
stays for the whole life of the screen:
const playerY = useRef(new Animated.Value(0)).current;
To jump, go up to JUMP_HEIGHT in 350 ms, then back to 0 in 350 ms. Animated.sequence runs them one
after the other:
Animated.sequence([Animated.timing(playerY, { toValue: JUMP_HEIGHT, duration: 350, useNativeDriver: false }),Animated.timing(playerY, { toValue: 0, duration: 350, useNativeDriver: false }),]).start();
Then draw the square with <Animated.View style={{ bottom: playerY }}>. A normal View cannot read an
Animated.Value; it must be an Animated.View.
Animated.spring is the other way to move a value. Instead of a time, it acts like a spring, so the
square can bounce a little when it lands.
useNativeDriver: false is needed here because we move bottom, which changes layout. The faster
native driver only works for transform and opacity.
playerY is now not in game any more. Animated moves the square without rendering the
component again, so the jump stays smooth even while the game loop is busy.
People often write new Animated.Value(0) without useRef. Then every render makes a brand new value
at 0, and the jump snaps back to the ground in the middle.
Big games in React Native use a library called Reanimated. It runs animations on their own thread and
can do much more. The idea is the same: a value, a target, and a time. Start with Animated.
Code tour
Click a line number with a ring to read the note for that line.
Practice
Short drills. Take your time and read the code before you answer.
1function Jumper() {2 const playerY = useRef(new Animated.Value(0)).current;3 console.log("render");45 function jump() {6 Animated.timing(playerY, { toValue: 150, duration: 350, useNativeDriver: false }).start();7 }89 return (10 <Pressable style={{ flex: 1 }} onPressIn={jump}>11 <Animated.View style={{ position: "absolute", bottom: playerY, width: 40, height: 40 }} />12 </Pressable>13 );14}1516// The screen appears, then you tap once and the square rises to 150.17// Count in the real app (not the extra development check).
jumpHeightAt(ms) says how high the square is ms milliseconds after the tap, for a straight-line jump (what Easing.linear would give). It goes up to 150 in 350 ms, back down to 0 by 700 ms, and then stays on the ground. This is the math Animated.timing does for you. One part is wrong: after the jump it goes under the ground. Fix it.Animated. The game loop only moves the obstacle. Tap to jump and compare it with the jump from the last topic.1import { useEffect, useRef, useState } from "react";2import { Animated, Pressable, StyleSheet, Text, View } from "react-native";34const SPEED = 10;5const SCREEN_WIDTH = 400;6const OBSTACLE_WIDTH = 30;
Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.
duration values to 1000. The jump becomes slow, like on the moon. Put them back to 350.Change the second Animated.timing(...) to Animated.spring(playerY, { toValue: 0, useNativeDriver: false }). The square now bounces a little when it lands.Quick check
3 questions. Each one explains itself after you answer.
- 1 / 3What does
Animated.timing(playerY, { toValue: 150, duration: 350, useNativeDriver: false }).start()do? - 2 / 3Why is the value made with
useRef(new Animated.Value(0)).current? - 3 / 3You write
<View style={{ bottom: playerY }}>with anAnimated.Value. What goes wrong?
Explain it back
How confident are you with Simple animation?
Done
Animated.timing call and say where the value goes, how long it takes, and what it moves on screen.