More powerful alternative to Animated library for React Native with UI thread animations and advanced gesture handling.
—
Mathematical functions for smooth value transitions, custom animation curves, and color interpolation that enable sophisticated animation effects.
Maps values from one range to another using linear interpolation.
/**
* Maps a value from an input range to an output range using linear interpolation
* @param value - The input value to interpolate
* @param inputRange - Array of input values (must be monotonically increasing)
* @param outputRange - Array of corresponding output values
* @param extrapolate - How to handle values outside the input range
* @returns Interpolated output value
*/
function interpolate(
value: number,
inputRange: readonly number[],
outputRange: readonly number[],
extrapolate?: ExtrapolationType
): number;
/**
* Clamps a value between minimum and maximum bounds
* @param value - Value to clamp
* @param min - Minimum allowed value
* @param max - Maximum allowed value
* @returns Clamped value
*/
function clamp(value: number, min: number, max: number): number;
enum Extrapolation {
/** Extend the interpolation beyond the ranges */
EXTEND = "extend",
/** Clamp to the edge values of the ranges */
CLAMP = "clamp",
/** Return the input value as-is when outside ranges */
IDENTITY = "identity"
}
type ExtrapolationType = Extrapolation;
/** @deprecated Use Extrapolation instead */
const Extrapolate = Extrapolation;Usage Examples:
import React from "react";
import Animated, {
useSharedValue,
useAnimatedStyle,
interpolate,
Extrapolation,
clamp,
withTiming,
useDerivedValue
} from "react-native-reanimated";
import { Button } from "react-native";
const InterpolationExample = () => {
const progress = useSharedValue(0);
// Basic interpolation
const animatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(progress.value, [0, 1], [0.2, 1]),
transform: [
{
scale: interpolate(progress.value, [0, 0.5, 1], [1, 1.5, 1]),
},
{
rotate: `${interpolate(progress.value, [0, 1], [0, 360])}deg`,
},
],
}));
// Interpolation with different extrapolation modes
const extendedStyle = useAnimatedStyle(() => ({
// Extends beyond range
translateX: interpolate(
progress.value,
[0, 1],
[0, 100],
Extrapolation.EXTEND
),
// Clamps to range bounds
translateY: interpolate(
progress.value,
[0, 1],
[0, 100],
Extrapolation.CLAMP
),
}));
// Complex multi-point interpolation
const complexStyle = useAnimatedStyle(() => ({
backgroundColor: progress.value < 0.33 ? "red" :
progress.value < 0.66 ? "green" : "blue",
borderRadius: interpolate(
progress.value,
[0, 0.25, 0.5, 0.75, 1],
[0, 10, 25, 10, 0]
),
}));
// Using clamp utility
const clampedValue = useDerivedValue(() =>
clamp(progress.value * 150, 50, 100)
);
const clampedStyle = useAnimatedStyle(() => ({
width: clampedValue.value,
height: clampedValue.value,
}));
const animate = () => {
progress.value = withTiming(progress.value === 0 ? 1 : 0, {
duration: 2000
});
};
return (
<>
<Button title="Animate" onPress={animate} />
{/* Basic interpolation */}
<Animated.View
style={[
{ width: 100, height: 100, backgroundColor: "lightblue", margin: 10 },
animatedStyle,
]}
/>
{/* Extended interpolation */}
<Animated.View
style={[
{ width: 50, height: 50, backgroundColor: "lightgreen", margin: 10 },
extendedStyle,
]}
/>
{/* Complex interpolation */}
<Animated.View
style={[
{ width: 80, height: 80, margin: 10 },
complexStyle,
]}
/>
{/* Clamped size */}
<Animated.View
style={[
{ backgroundColor: "lightcoral", margin: 10 },
clampedStyle,
]}
/>
</>
);
};Interpolates between color values in different color spaces.
/**
* Interpolates between color values
* @param value - The input value to interpolate
* @param inputRange - Array of input values (must be monotonically increasing)
* @param outputRange - Array of color strings to interpolate between
* @param colorSpace - Color space for interpolation (RGB or HSV)
* @param options - Additional interpolation options
* @returns Interpolated color string
*/
function interpolateColor(
value: number,
inputRange: readonly number[],
outputRange: readonly string[],
colorSpace?: ColorSpace,
options?: InterpolationOptions
): string;
enum ColorSpace {
RGB = "rgb",
HSV = "hsv"
}
interface InterpolationOptions {
/** Gamma correction for RGB interpolation */
gamma?: number;
/** Whether to use shorter or longer path in HSV */
useCorrectedHSVInterpolation?: boolean;
}
/**
* Hook for creating reusable color interpolation configurations
* @param inputRange - Input range for interpolation
* @param outputRange - Output color range
* @param colorSpace - Color space to use
* @returns Interpolation configuration function
*/
function useInterpolateConfig(
inputRange: readonly number[],
outputRange: readonly string[],
colorSpace?: ColorSpace
): (value: number) => string;Usage Examples:
import React from "react";
import Animated, {
useSharedValue,
useAnimatedStyle,
interpolateColor,
ColorSpace,
withTiming,
useInterpolateConfig,
useDerivedValue
} from "react-native-reanimated";
import { Button } from "react-native";
const ColorInterpolationExample = () => {
const progress = useSharedValue(0);
// RGB color interpolation
const rgbStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
progress.value,
[0, 0.5, 1],
["#FF0000", "#00FF00", "#0000FF"], // Red -> Green -> Blue
ColorSpace.RGB
),
}));
// HSV color interpolation (smoother transitions)
const hsvStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
progress.value,
[0, 1],
["#FF0000", "#0000FF"], // Red -> Blue via HSV
ColorSpace.HSV
),
}));
// Complex color progression
const rainbowStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
progress.value,
[0, 0.16, 0.33, 0.5, 0.66, 0.83, 1],
[
"#FF0000", // Red
"#FF8000", // Orange
"#FFFF00", // Yellow
"#00FF00", // Green
"#0000FF", // Blue
"#8000FF", // Indigo
"#FF00FF", // Violet
],
ColorSpace.HSV
),
}));
// Using interpolation config hook
const colorConfig = useInterpolateConfig(
[0, 0.3, 0.7, 1],
["#1a1a1a", "#ff6b6b", "#4ecdc4", "#45b7d1"],
ColorSpace.RGB
);
const configStyle = useAnimatedStyle(() => ({
backgroundColor: colorConfig(progress.value),
}));
// Color with alpha interpolation
const alphaStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
progress.value,
[0, 1],
["rgba(255, 0, 0, 0.2)", "rgba(255, 0, 0, 1.0)"]
),
}));
// Border color animation
const borderStyle = useAnimatedStyle(() => ({
borderColor: interpolateColor(
progress.value,
[0, 1],
["#cccccc", "#ff0000"],
ColorSpace.RGB
),
borderWidth: 3,
}));
const animate = () => {
progress.value = withTiming(progress.value === 0 ? 1 : 0, {
duration: 3000
});
};
return (
<>
<Button title="Animate Colors" onPress={animate} />
{/* RGB interpolation */}
<Animated.View
style={[
{ width: 100, height: 50, margin: 5, borderRadius: 5 },
rgbStyle,
]}
/>
{/* HSV interpolation */}
<Animated.View
style={[
{ width: 100, height: 50, margin: 5, borderRadius: 5 },
hsvStyle,
]}
/>
{/* Rainbow progression */}
<Animated.View
style={[
{ width: 100, height: 50, margin: 5, borderRadius: 5 },
rainbowStyle,
]}
/>
{/* Config-based interpolation */}
<Animated.View
style={[
{ width: 100, height: 50, margin: 5, borderRadius: 5 },
configStyle,
]}
/>
{/* Alpha interpolation */}
<Animated.View
style={[
{ width: 100, height: 50, margin: 5, borderRadius: 5 },
alphaStyle,
]}
/>
{/* Border color */}
<Animated.View
style={[
{
width: 100,
height: 50,
margin: 5,
borderRadius: 5,
backgroundColor: "white"
},
borderStyle,
]}
/>
</>
);
};Utility functions for color validation, conversion, and processing for animations.
/**
* Checks if a value is a valid color string or number
* @param value - Value to test for color validity
* @returns True if value is a valid color
*/
function isColor(value: unknown): boolean;
/**
* Converts a color value to RGBA array format
* @param color - Color value (string, number, or hex)
* @returns RGBA array with values from 0-1
*/
function convertToRGBA(color: unknown): ParsedColorArray;
/**
* Processes color values for platform-specific rendering
* @param color - Raw color value to process
* @returns Processed color number, null, or undefined
*/
function processColor(color: unknown): number | null | undefined;
type ParsedColorArray = [number, number, number, number]; // [r, g, b, a]Usage Examples:
import { isColor, convertToRGBA, processColor } from "react-native-reanimated";
// Color validation
const validateColors = () => {
console.log(isColor("red")); // true
console.log(isColor("#FF0000")); // true
console.log(isColor("rgb(255,0,0)")); // true
console.log(isColor("invalid")); // false
console.log(isColor(123)); // false
};
// Color conversion for animations
const useColorAnimation = () => {
const colorValue = useSharedValue("red");
const animatedStyle = useAnimatedStyle(() => {
// Convert color to RGBA for processing
const [r, g, b, a] = convertToRGBA(colorValue.value);
return {
backgroundColor: `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`,
};
});
return animatedStyle;
};
// Color processing for platform compatibility
const processColors = () => {
const colors = ["red", "#FF0000", "rgb(255,0,0)", null, undefined];
colors.forEach(color => {
const processed = processColor(color);
console.log(`${color} -> ${processed}`);
});
};
// Advanced color interpolation with conversion
const ColorTransition = () => {
const progress = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => {
// Convert start and end colors to RGBA
const startColor = convertToRGBA("red"); // [1, 0, 0, 1]
const endColor = convertToRGBA("blue"); // [0, 0, 1, 1]
// Manually interpolate each component
const r = interpolate(progress.value, [0, 1], [startColor[0], endColor[0]]);
const g = interpolate(progress.value, [0, 1], [startColor[1], endColor[1]]);
const b = interpolate(progress.value, [0, 1], [startColor[2], endColor[2]]);
const a = interpolate(progress.value, [0, 1], [startColor[3], endColor[3]]);
return {
backgroundColor: `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`,
};
});
return <Animated.View style={animatedStyle} />;
};Predefined and custom easing functions for natural animation curves.
const Easing: {
/** Linear easing function (f(t) = t) */
linear: EasingFunction;
/** Default ease function with gentle acceleration and deceleration */
ease: EasingFunction;
/** Quadratic easing (f(t) = t²) */
quad: EasingFunction;
/** Cubic easing (f(t) = t³) */
cubic: EasingFunction;
/** Polynomial easing with custom exponent */
poly(n: number): EasingFunction;
/** Sinusoidal easing */
sin: EasingFunction;
/** Circular easing */
circle: EasingFunction;
/** Exponential easing */
exp: EasingFunction;
/** Elastic spring easing with bounce effect */
elastic(bounciness?: number): EasingFunction;
/** Back easing with overshoot effect */
back(s?: number): EasingFunction;
/** Bouncing easing with multiple bounces */
bounce: EasingFunction;
/** Cubic bezier curve easing */
bezier(x1: number, y1: number, x2: number, y2: number): EasingFunction;
/** Apply easing in forward direction */
in(easing: EasingFunction): EasingFunction;
/** Apply easing in reverse direction */
out(easing: EasingFunction): EasingFunction;
/** Apply easing in both directions (symmetric) */
inOut(easing: EasingFunction): EasingFunction;
};
type EasingFunction = (value: number) => number;
interface EasingFunctionFactory {
factory(): EasingFunction;
}Usage Examples:
import React from "react";
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
Easing
} from "react-native-reanimated";
import { Button } from "react-native";
const EasingExample = () => {
const progress1 = useSharedValue(0);
const progress2 = useSharedValue(0);
const progress3 = useSharedValue(0);
const progress4 = useSharedValue(0);
// Linear easing
const linearStyle = useAnimatedStyle(() => ({
transform: [{ translateX: progress1.value * 200 }],
}));
// Ease out quadratic
const easeOutStyle = useAnimatedStyle(() => ({
transform: [{ translateX: progress2.value * 200 }],
}));
// Bounce easing
const bounceStyle = useAnimatedStyle(() => ({
transform: [{ translateX: progress3.value * 200 }],
}));
// Custom bezier easing
const bezierStyle = useAnimatedStyle(() => ({
transform: [{ translateX: progress4.value * 200 }],
}));
const animateLinear = () => {
progress1.value = withTiming(progress1.value === 0 ? 1 : 0, {
duration: 1000,
easing: Easing.linear,
});
};
const animateEaseOut = () => {
progress2.value = withTiming(progress2.value === 0 ? 1 : 0, {
duration: 1000,
easing: Easing.out(Easing.quad),
});
};
const animateBounce = () => {
progress3.value = withTiming(progress3.value === 0 ? 1 : 0, {
duration: 1500,
easing: Easing.bounce,
});
};
const animateBezier = () => {
progress4.value = withTiming(progress4.value === 0 ? 1 : 0, {
duration: 1000,
easing: Easing.bezier(0.25, 0.1, 0.25, 1), // CSS ease
});
};
return (
<>
<Button title="Linear" onPress={animateLinear} />
<Animated.View
style={[
{ width: 50, height: 50, backgroundColor: "red", margin: 5 },
linearStyle,
]}
/>
<Button title="Ease Out Quad" onPress={animateEaseOut} />
<Animated.View
style={[
{ width: 50, height: 50, backgroundColor: "green", margin: 5 },
easeOutStyle,
]}
/>
<Button title="Bounce" onPress={animateBounce} />
<Animated.View
style={[
{ width: 50, height: 50, backgroundColor: "blue", margin: 5 },
bounceStyle,
]}
/>
<Button title="Bezier" onPress={animateBezier} />
<Animated.View
style={[
{ width: 50, height: 50, backgroundColor: "purple", margin: 5 },
bezierStyle,
]}
/>
</>
);
};Complex easing combinations and custom curves.
Custom Easing Functions:
import { Easing } from "react-native-reanimated";
// Create custom easing functions
const customEasings = {
// Elastic with custom bounciness
elasticOut: Easing.out(Easing.elastic(2)),
// Back with overshoot
backInOut: Easing.inOut(Easing.back(1.7)),
// Custom polynomial
fastSlowFast: Easing.inOut(Easing.poly(3)),
// Complex bezier curves
cssEase: Easing.bezier(0.25, 0.1, 0.25, 1),
cssEaseIn: Easing.bezier(0.42, 0, 1, 1),
cssEaseOut: Easing.bezier(0, 0, 0.58, 1),
cssEaseInOut: Easing.bezier(0.42, 0, 0.58, 1),
// Material Design curves
materialStandard: Easing.bezier(0.4, 0.0, 0.2, 1),
materialDecelerate: Easing.bezier(0.0, 0.0, 0.2, 1),
materialAccelerate: Easing.bezier(0.4, 0.0, 1, 1),
// Custom stepped function
stepped: (steps: number) => (t: number) => Math.floor(t * steps) / steps,
};Advanced interpolation patterns and utilities.
interface InterpolateConfig {
inputRange: readonly number[];
outputRange: readonly (string | number)[];
extrapolate?: ExtrapolationType;
extrapolateLeft?: ExtrapolationType;
extrapolateRight?: ExtrapolationType;
}
interface InterpolateHSV {
h: number;
s: number;
v: number;
}
interface InterpolateRGB {
r: number;
g: number;
b: number;
}Advanced Interpolation Example:
import React from "react";
import Animated, {
useSharedValue,
useAnimatedStyle,
interpolate,
Extrapolation,
withTiming
} from "react-native-reanimated";
const AdvancedInterpolationExample = () => {
const scrollY = useSharedValue(0);
// Complex header transformation
const headerStyle = useAnimatedStyle(() => {
const headerHeight = 200;
const minHeight = 80;
return {
height: interpolate(
scrollY.value,
[0, headerHeight - minHeight],
[headerHeight, minHeight],
Extrapolation.CLAMP
),
opacity: interpolate(
scrollY.value,
[0, headerHeight / 2, headerHeight],
[1, 0.8, 0.3],
Extrapolation.CLAMP
),
transform: [
{
scale: interpolate(
scrollY.value,
[0, headerHeight],
[1, 0.9],
Extrapolation.CLAMP
),
},
],
};
});
// Parallax background
const backgroundStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: interpolate(
scrollY.value,
[0, 300],
[0, -100],
Extrapolation.EXTEND // Allow over-scroll effect
),
},
{
scale: interpolate(
scrollY.value,
[-100, 0, 300],
[1.2, 1, 0.8],
{
extrapolateLeft: Extrapolation.CLAMP,
extrapolateRight: Extrapolation.EXTEND,
}
),
},
],
}));
return (
<>
<Animated.View style={[{ position: "absolute", top: 0 }, backgroundStyle]}>
{/* Background content */}
</Animated.View>
<Animated.View style={headerStyle}>
{/* Header content */}
</Animated.View>
<Animated.ScrollView
onScroll={(event) => {
scrollY.value = event.nativeEvent.contentOffset.y;
}}
scrollEventThrottle={16}
>
{/* Scroll content */}
</Animated.ScrollView>
</>
);
};type ExtrapolationType = Extrapolation | {
extrapolateLeft?: Extrapolation;
extrapolateRight?: Extrapolation;
};
interface ExtrapolationConfig {
extrapolateLeft?: ExtrapolationType;
extrapolateRight?: ExtrapolationType;
}
type ParsedColorArray = readonly [number, number, number, number]; // RGBA
interface InterpolationOptions {
gamma?: number;
useCorrectedHSVInterpolation?: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-react-native-reanimated