CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-web

React Native for Web is a comprehensive compatibility library that enables React Native components and APIs to run seamlessly on web browsers using React DOM.

Pending
Overview
Eval results
Files

animation.mddocs/

Animation

React Native's Animated API adapted for web with full support for declarative animations, timing functions, spring physics, and composition utilities for building complex animated UIs.

Animated

The main Animated API providing declarative animation capabilities with configurable transforms, value management, and timing control for building fluid, maintainable animations.

const Animated: {
  // Value Classes
  Value: typeof AnimatedValue;
  ValueXY: typeof AnimatedValueXY;
  Color: typeof AnimatedColor;
  
  // Animation Functions
  timing: (value: AnimatedValue | AnimatedValueXY | AnimatedColor, config: TimingAnimationConfig) => CompositeAnimation;
  spring: (value: AnimatedValue | AnimatedValueXY | AnimatedColor, config: SpringAnimationConfig) => CompositeAnimation;
  decay: (value: AnimatedValue | AnimatedValueXY | AnimatedColor, config: DecayAnimationConfig) => CompositeAnimation;
  
  // Composition Functions
  parallel: (animations: CompositeAnimation[], config?: ParallelConfig) => CompositeAnimation;
  sequence: (animations: CompositeAnimation[]) => CompositeAnimation;
  stagger: (time: number, animations: CompositeAnimation[]) => CompositeAnimation;
  delay: (time: number) => CompositeAnimation;
  loop: (animation: CompositeAnimation, config?: LoopAnimationConfig) => CompositeAnimation;
  
  // Math Operations
  add: (a: AnimatedNode | number, b: AnimatedNode | number) => AnimatedAddition;
  subtract: (a: AnimatedNode | number, b: AnimatedNode | number) => AnimatedSubtraction;
  multiply: (a: AnimatedNode | number, b: AnimatedNode | number) => AnimatedMultiplication;
  divide: (a: AnimatedNode | number, b: AnimatedNode | number) => AnimatedDivision;
  modulo: (a: AnimatedNode, modulus: number) => AnimatedModulo;
  diffClamp: (a: AnimatedNode, min: number, max: number) => AnimatedDiffClamp;
  
  // Event Handling
  event: (argMapping: Mapping[], config: EventConfig) => Function;
  forkEvent: (event: AnimatedEvent | Function, listener: Function) => AnimatedEvent | Function;
  unforkEvent: (event: AnimatedEvent | Function, listener: Function) => void;
  
  // Components
  View: typeof AnimatedView;
  Text: typeof AnimatedText;
  Image: typeof AnimatedImage;
  ScrollView: typeof AnimatedScrollView;
  FlatList: typeof AnimatedFlatList;
  SectionList: typeof AnimatedSectionList;
  
  // Utilities
  createAnimatedComponent: <T>(Component: T) => T;
  attachNativeEvent: (viewRef: any, eventName: string, argMapping: Mapping[]) => void;
  
  // Type Exports
  Node: typeof AnimatedNode;
  Interpolation: typeof AnimatedInterpolation;
  Event: typeof AnimatedEvent;
};

Easing

Comprehensive easing functions library providing mathematically accurate timing curves for animations. Includes predefined animations, standard mathematical functions, and helper functions for creating custom easing behaviors.

const Easing: {
  // Predefined animations
  ease: (t: number) => number;
  bounce: (t: number) => number;
  back: (s?: number) => (t: number) => number;
  elastic: (bounciness?: number) => (t: number) => number;
  
  // Standard functions
  linear: (t: number) => number;
  quad: (t: number) => number;
  cubic: (t: number) => number;
  poly: (n: number) => (t: number) => number;
  
  // Mathematical functions
  sin: (t: number) => number;
  circle: (t: number) => number;
  exp: (t: number) => number;
  bezier: (x1: number, y1: number, x2: number, y2: number) => (t: number) => number;
  
  // Stepping functions
  step0: (n: number) => number;
  step1: (n: number) => number;
  
  // Direction helpers
  in: (easing: (t: number) => number) => (t: number) => number;
  out: (easing: (t: number) => number) => (t: number) => number;
  inOut: (easing: (t: number) => number) => (t: number) => number;
};

Web Implementation: All easing functions are implemented using pure JavaScript mathematical functions, providing consistent behavior across all platforms and browsers.

Predefined Animations

// Simple inertial animation, similar to CSS ease
Easing.ease(t: number): number

// Bouncing animation with multiple bounces
Easing.bounce(t: number): number

// Animation that goes slightly back before moving forward
Easing.back(s?: number): (t: number) => number

// Spring-like elastic animation with configurable bounciness
Easing.elastic(bounciness?: number): (t: number) => number

Standard Mathematical Functions

// Linear timing (no easing)
Easing.linear(t: number): number

// Quadratic timing (t²)
Easing.quad(t: number): number

// Cubic timing (t³)
Easing.cubic(t: number): number

// Power timing (t^n)
Easing.poly(n: number): (t: number) => number

Advanced Mathematical Functions

// Sinusoidal timing
Easing.sin(t: number): number

// Circular timing
Easing.circle(t: number): number

// Exponential timing
Easing.exp(t: number): number

// Cubic Bézier curve (like CSS transition-timing-function)
Easing.bezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number

Direction Helpers

// Run easing function forwards (identity function)
Easing.in(easing: (t: number) => number): (t: number) => number

// Run easing function backwards
Easing.out(easing: (t: number) => number): (t: number) => number

// Make easing function symmetrical (ease in for first half, ease out for second half)
Easing.inOut(easing: (t: number) => number): (t: number) => number

Usage:

import { Animated, Easing } from "react-native-web";

function EasingExample() {
  const fadeAnim = new Animated.Value(0);
  const slideAnim = new Animated.Value(-100);

  const startAnimation = () => {
    Animated.parallel([
      // Fade in with custom cubic bezier
      Animated.timing(fadeAnim, {
        toValue: 1,
        duration: 500,
        easing: Easing.bezier(0.25, 0.1, 0.25, 1), // CSS ease
        useNativeDriver: false,
      }),
      
      // Slide in with elastic bounce
      Animated.timing(slideAnim, {
        toValue: 0,
        duration: 800,
        easing: Easing.elastic(1.5),
        useNativeDriver: false,
      }),
      
      // Complex custom easing using helpers
      Animated.timing(rotateAnim, {
        toValue: 360,
        duration: 1000,
        easing: Easing.inOut(Easing.back(2)),
        useNativeDriver: false,
      }),
    ]).start();
  };

  return (
    <Animated.View
      style={{
        opacity: fadeAnim,
        transform: [
          { translateX: slideAnim },
          { rotate: rotateAnim.interpolate({
            inputRange: [0, 360],
            outputRange: ['0deg', '360deg']
          })}
        ],
      }}
    >
      <Text>Animated with custom easing!</Text>
    </Animated.View>
  );
}

// Compare different easing functions
const easingComparison = {
  linear: Easing.linear,
  ease: Easing.ease,
  easeOut: Easing.out(Easing.quad),
  easeInOut: Easing.inOut(Easing.cubic),
  bounce: Easing.bounce,
  elastic: Easing.elastic(1),
  back: Easing.back(),
};

Value Classes

Animated.Value

Standard animated value class for driving single-property animations.

class AnimatedValue extends AnimatedNode {
  constructor(value: number, config?: AnimatedValueConfig): AnimatedValue;
  setValue(value: number): void;
  setOffset(offset: number): void;
  flattenOffset(): void;
  extractOffset(): void;
  addListener(callback: ValueListenerCallback): string;
  removeListener(id: string): void;
  removeAllListeners(): void;
  stopAnimation(callback?: (value: number) => void): void;
  resetAnimation(callback?: (value: number) => void): void;
  interpolate(config: InterpolationConfigType): AnimatedInterpolation;
  animate(animation: Animation, callback?: EndCallback): void;
  stopTracking(): void;
  track(tracking: AnimatedTracking): void;
}

Usage:

import { Animated, View } from "react-native-web";

function FadeInView({ children }) {
  const fadeAnim = new Animated.Value(0);

  React.useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: false
    }).start();
  }, [fadeAnim]);

  return (
    <Animated.View style={{ opacity: fadeAnim }}>
      {children}
    </Animated.View>
  );
}

// Advanced value manipulation
function ComplexAnimation() {
  const translateX = new Animated.Value(0);
  const scale = new Animated.Value(1);

  // Set initial value
  translateX.setValue(50);
  
  // Add offset (current value becomes offset + value)
  translateX.setOffset(100);
  translateX.setValue(0); // Now animates from 100
  
  // Listen to value changes
  const listenerId = translateX.addListener(({ value }) => {
    console.log(`TranslateX: ${value}`);
  });

  // Interpolate for different properties
  const backgroundColor = translateX.interpolate({
    inputRange: [0, 100],
    outputRange: ['rgba(255,0,0,0.5)', 'rgba(0,0,255,0.5)'],
    extrapolate: 'clamp'
  });

  return (
    <Animated.View
      style={{
        transform: [
          { translateX },
          { scale }
        ],
        backgroundColor
      }}
    />
  );
}

Animated.ValueXY

2D animated value class for driving pan gestures and multi-dimensional animations.

class AnimatedValueXY extends AnimatedNode {
  x: AnimatedValue;
  y: AnimatedValue;
  
  constructor(valueIn?: { x: number | AnimatedValue; y: number | AnimatedValue }, config?: AnimatedValueConfig): AnimatedValueXY;
  setValue(value: { x: number; y: number }): void;
  setOffset(offset: { x: number; y: number }): void;
  flattenOffset(): void;
  extractOffset(): void;
  stopAnimation(callback?: (value: { x: number; y: number }) => void): void;
  resetAnimation(callback?: (value: { x: number; y: number }) => void): void;
  addListener(callback: ValueXYListenerCallback): string;
  removeListener(id: string): void;
  removeAllListeners(): void;
  getLayout(): { left: AnimatedValue; top: AnimatedValue };
  getTranslateTransform(): [{ translateX: AnimatedValue }, { translateY: AnimatedValue }];
}

Usage:

// Pan gesture with ValueXY
function DraggableBox() {
  const pan = new Animated.ValueXY();
  const panGesture = PanGestureHandler.create({
    onGestureEvent: Animated.event(
      [{ nativeEvent: { translationX: pan.x, translationY: pan.y } }],
      { useNativeDriver: false }
    ),
    onHandlerStateChange: (event) => {
      if (event.nativeEvent.oldState === State.ACTIVE) {
        // Snap back to center
        Animated.spring(pan, {
          toValue: { x: 0, y: 0 },
          useNativeDriver: false
        }).start();
      }
    }
  });

  return (
    <PanGestureHandler {...panGesture}>
      <Animated.View
        style={{
          transform: pan.getTranslateTransform(),
          width: 100,
          height: 100,
          backgroundColor: 'blue'
        }}
      />
    </PanGestureHandler>
  );
}

// Complex 2D animation
function Orbit() {
  const position = new Animated.ValueXY({ x: 0, y: 0 });
  const angle = new Animated.Value(0);

  React.useEffect(() => {
    const animateOrbit = () => {
      const radius = 50;
      angle.setValue(0);
      
      Animated.timing(angle, {
        toValue: 2 * Math.PI,
        duration: 2000,
        useNativeDriver: false
      }).start(() => animateOrbit());
    };

    animateOrbit();
  }, []);

  // Convert polar to cartesian coordinates
  const x = Animated.multiply(
    Animated.add(Math.cos, angle),
    radius
  );
  const y = Animated.multiply(
    Animated.add(Math.sin, angle),
    radius
  );

  return (
    <Animated.View
      style={{
        position: 'absolute',
        left: x,
        top: y,
        width: 20,
        height: 20,
        backgroundColor: 'red',
        borderRadius: 10
      }}
    />
  );
}

Animated.Color

Animated value class for color animations with RGBA channel support.

class AnimatedColor extends AnimatedNode {
  r: AnimatedValue;
  g: AnimatedValue;
  b: AnimatedValue;
  a: AnimatedValue;
  
  constructor(valueIn?: string | { r: number; g: number; b: number; a: number }): AnimatedColor;
  setValue(value: string): void;
}

Animation Functions

timing()

Animates a value along a timed easing curve with configurable duration and easing function.

Animated.timing(
  value: AnimatedValue | AnimatedValueXY | AnimatedColor,
  config: {
    toValue: number | AnimatedValue | { x: number; y: number } | string;
    duration?: number; // default: 500
    easing?: EasingFunction; // default: Easing.inOut(Easing.ease)
    delay?: number; // default: 0
    useNativeDriver?: boolean; // default: false
    onComplete?: (result: EndResult) => void;
  }
): CompositeAnimation

Usage:

// Basic timing animation
const opacity = new Animated.Value(0);

Animated.timing(opacity, {
  toValue: 1,
  duration: 300,
  useNativeDriver: false
}).start();

// Custom easing functions
import { Easing } from "react-native-web";

Animated.timing(opacity, {
  toValue: 1,
  duration: 500,
  easing: Easing.bezier(0.25, 0.1, 0.25, 1), // Custom bezier
  useNativeDriver: false
}).start();

// Sequential timing with callbacks
function SequentialAnimation() {
  const slideIn = new Animated.Value(-100);
  const fadeIn = new Animated.Value(0);

  const animateIn = () => {
    Animated.timing(slideIn, {
      toValue: 0,
      duration: 300,
      easing: Easing.out(Easing.back(1.7)),
      useNativeDriver: false
    }).start(({ finished }) => {
      if (finished) {
        Animated.timing(fadeIn, {
          toValue: 1,
          duration: 200,
          useNativeDriver: false
        }).start();
      }
    });
  };

  return (
    <Animated.View
      style={{
        transform: [{ translateX: slideIn }],
        opacity: fadeIn
      }}
    />
  );
}

spring()

Animates a value according to an analytical spring model based on damped harmonic oscillation.

Animated.spring(
  value: AnimatedValue | AnimatedValueXY | AnimatedColor,
  config: {
    toValue: number | AnimatedValue | { x: number; y: number };
    restDisplacementThreshold?: number; // default: 0.001
    restSpeedThreshold?: number; // default: 0.001
    velocity?: number | { x: number; y: number }; // default: 0
    bounciness?: number; // default: 8
    speed?: number; // default: 12
    tension?: number; // alternative to bounciness/speed
    friction?: number; // alternative to bounciness/speed
    stiffness?: number; // alternative spring config
    damping?: number; // alternative spring config
    mass?: number; // default: 1
    useNativeDriver?: boolean; // default: false
    onComplete?: (result: EndResult) => void;
  }
): CompositeAnimation

Usage:

// Bouncy spring animation
const scale = new Animated.Value(0);

Animated.spring(scale, {
  toValue: 1,
  bounciness: 15,
  speed: 8,
  useNativeDriver: false
}).start();

// Physics-based spring
Animated.spring(scale, {
  toValue: 1,
  tension: 100,
  friction: 8,
  velocity: 0.5,
  useNativeDriver: false
}).start();

// Interactive spring with gesture
function SpringButton({ onPress, children }) {
  const scale = new Animated.Value(1);
  const opacity = new Animated.Value(1);

  const animateIn = () => {
    Animated.parallel([
      Animated.spring(scale, {
        toValue: 0.95,
        tension: 300,
        friction: 10,
        useNativeDriver: false
      }),
      Animated.timing(opacity, {
        toValue: 0.8,
        duration: 100,
        useNativeDriver: false
      })
    ]).start();
  };

  const animateOut = () => {
    Animated.parallel([
      Animated.spring(scale, {
        toValue: 1,
        tension: 300,
        friction: 10,
        useNativeDriver: false
      }),
      Animated.timing(opacity, {
        toValue: 1,
        duration: 100,
        useNativeDriver: false
      })
    ]).start();
  };

  return (
    <TouchableWithoutFeedback
      onPressIn={animateIn}
      onPressOut={animateOut}
      onPress={onPress}
    >
      <Animated.View
        style={{
          transform: [{ scale }],
          opacity
        }}
      >
        {children}
      </Animated.View>
    </TouchableWithoutFeedback>
  );
}

decay()

Animates a value from an initial velocity to zero based on a decay coefficient.

Animated.decay(
  value: AnimatedValue | AnimatedValueXY | AnimatedColor,
  config: {
    velocity: number | { x: number; y: number };
    deceleration?: number; // default: 0.998
    useNativeDriver?: boolean; // default: false
    onComplete?: (result: EndResult) => void;
  }
): CompositeAnimation

Usage:

// Scroll momentum simulation
function MomentumScroll() {
  const scrollY = new Animated.Value(0);
  let lastScrollY = 0;
  let velocity = 0;

  const handleScroll = (event) => {
    const currentScrollY = event.nativeEvent.contentOffset.y;
    velocity = currentScrollY - lastScrollY;
    lastScrollY = currentScrollY;
    scrollY.setValue(currentScrollY);
  };

  const handleScrollEnd = () => {
    if (Math.abs(velocity) > 0.1) {
      Animated.decay(scrollY, {
        velocity: velocity,
        deceleration: 0.995,
        useNativeDriver: false
      }).start();
    }
  };

  return (
    <ScrollView
      onScroll={handleScroll}
      onScrollEndDrag={handleScrollEnd}
      scrollEventThrottle={16}
    >
      {/* Content */}
    </ScrollView>
  );
}

Composition Functions

parallel()

Starts multiple animations simultaneously with optional coordination.

Animated.parallel(
  animations: CompositeAnimation[],
  config?: {
    stopTogether?: boolean; // default: true
  }
): CompositeAnimation

sequence()

Runs animations in sequential order, waiting for each to complete.

Animated.sequence(animations: CompositeAnimation[]): CompositeAnimation

stagger()

Starts animations in sequence with successive delays.

Animated.stagger(
  time: number,
  animations: CompositeAnimation[]
): CompositeAnimation

loop()

Continuously repeats an animation with configurable iterations.

Animated.loop(
  animation: CompositeAnimation,
  config?: {
    iterations?: number; // default: -1 (infinite)
    resetBeforeIteration?: boolean; // default: true
  }
): CompositeAnimation

Usage:

// Complex choreographed animation
function StaggeredCards() {
  const cards = [0, 1, 2, 3].map(() => ({
    opacity: new Animated.Value(0),
    translateY: new Animated.Value(50),
    scale: new Animated.Value(0.8)
  }));

  const animateIn = () => {
    const cardAnimations = cards.map(({ opacity, translateY, scale }) =>
      Animated.parallel([
        Animated.timing(opacity, {
          toValue: 1,
          duration: 300,
          useNativeDriver: false
        }),
        Animated.spring(translateY, {
          toValue: 0,
          tension: 100,
          friction: 8,
          useNativeDriver: false
        }),
        Animated.spring(scale, {
          toValue: 1,
          tension: 120,
          friction: 7,
          useNativeDriver: false
        })
      ])
    );

    // Stagger the card animations
    Animated.stagger(100, cardAnimations).start();
  };

  const pulseAnimation = () => {
    const pulseScale = new Animated.Value(1);
    
    return Animated.loop(
      Animated.sequence([
        Animated.timing(pulseScale, {
          toValue: 1.05,
          duration: 800,
          useNativeDriver: false
        }),
        Animated.timing(pulseScale, {
          toValue: 1,
          duration: 800,
          useNativeDriver: false
        })
      ]),
      { iterations: -1 }
    );
  };

  return (
    <View>
      {cards.map(({ opacity, translateY, scale }, index) => (
        <Animated.View
          key={index}
          style={{
            opacity,
            transform: [{ translateY }, { scale }]
          }}
        >
          <Text>Card {index + 1}</Text>
        </Animated.View>
      ))}
    </View>
  );
}

Math Operations

Combine animated values using mathematical operations for complex derived animations.

Animated.add(a: AnimatedNode | number, b: AnimatedNode | number): AnimatedAddition;
Animated.subtract(a: AnimatedNode | number, b: AnimatedNode | number): AnimatedSubtraction;
Animated.multiply(a: AnimatedNode | number, b: AnimatedNode | number): AnimatedMultiplication;
Animated.divide(a: AnimatedNode | number, b: AnimatedNode | number): AnimatedDivision;
Animated.modulo(a: AnimatedNode, modulus: number): AnimatedModulo;
Animated.diffClamp(a: AnimatedNode, min: number, max: number): AnimatedDiffClamp;

Usage:

// Complex derived animations
function ParallaxHeader() {
  const scrollY = new Animated.Value(0);
  const headerHeight = 200;

  // Clamp scroll for header transformation
  const headerTranslateY = Animated.diffClamp(
    scrollY,
    0,
    headerHeight
  ).interpolate({
    inputRange: [0, headerHeight],
    outputRange: [0, -headerHeight],
    extrapolate: 'clamp'
  });

  // Combine multiple values
  const headerScale = Animated.add(
    1,
    Animated.divide(scrollY, headerHeight * 2)
  );

  const headerOpacity = Animated.subtract(
    1,
    Animated.divide(scrollY, headerHeight)
  );

  return (
    <View>
      <Animated.View
        style={{
          height: headerHeight,
          transform: [
            { translateY: headerTranslateY },
            { scale: headerScale }
          ],
          opacity: headerOpacity
        }}
      >
        <Text>Parallax Header</Text>
      </Animated.View>
      
      <ScrollView
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: scrollY } } }],
          { useNativeDriver: false }
        )}
        scrollEventThrottle={16}
      >
        {/* Content */}
      </ScrollView>
    </View>
  );
}

// Mathematical operations for physics
function PhysicsAnimation() {
  const x = new Animated.Value(0);
  const velocity = new Animated.Value(0);
  
  // Kinetic energy calculation: KE = 0.5 * m * v²
  const kineticEnergy = Animated.multiply(
    0.5,
    Animated.multiply(velocity, velocity)
  );

  // Oscillation with sine wave
  const time = new Animated.Value(0);
  const amplitude = 50;
  
  const sinePosition = Animated.multiply(
    amplitude,
    // Note: In real implementation, you'd need to use interpolation
    // for trigonometric functions
    time.interpolate({
      inputRange: [0, Math.PI * 2],
      outputRange: [0, 1, 0, -1, 0],
      extrapolate: 'extend'
    })
  );

  return (
    <Animated.View
      style={{
        transform: [{ translateX: sinePosition }]
      }}
    />
  );
}

Event Handling

Animated.event()

Maps gesture or scroll events directly to animated values for high-performance interactions.

Animated.event(
  argMapping: Mapping[],
  config?: {
    useNativeDriver?: boolean; // default: false
    listener?: Function;
  }
): Function

Usage:

// Scroll-driven animations
function ScrollParallax() {
  const scrollY = new Animated.Value(0);

  return (
    <ScrollView
      onScroll={Animated.event(
        [{ nativeEvent: { contentOffset: { y: scrollY } } }],
        {
          useNativeDriver: false,
          listener: (event) => {
            // Additional scroll handling
            console.log('Scroll position:', event.nativeEvent.contentOffset.y);
          }
        }
      )}
      scrollEventThrottle={16}
    >
      <Animated.View
        style={{
          transform: [{
            translateY: scrollY.interpolate({
              inputRange: [0, 100],
              outputRange: [0, -50],
              extrapolate: 'clamp'
            })
          }]
        }}
      >
        {/* Parallax content */}
      </Animated.View>
    </ScrollView>
  );
}

// Pan gesture handling
function PanAnimation() {
  const pan = new Animated.ValueXY();

  return (
    <View>
      <Animated.View
        {...PanResponder.create({
          onMoveShouldSetPanResponder: () => true,
          onPanResponderGrant: () => {
            pan.setOffset({
              x: pan.x._value,
              y: pan.y._value
            });
          },
          onPanResponderMove: Animated.event(
            [null, { dx: pan.x, dy: pan.y }],
            { useNativeDriver: false }
          ),
          onPanResponderRelease: () => {
            pan.flattenOffset();
            Animated.spring(pan, {
              toValue: { x: 0, y: 0 },
              useNativeDriver: false
            }).start();
          }
        }).panHandlers}
        style={{
          transform: pan.getTranslateTransform()
        }}
      >
        {/* Draggable content */}
      </Animated.View>
    </View>
  );
}

Animated Components

Pre-built animated versions of common React Native components.

const AnimatedComponents: {
  View: AnimatedComponent<typeof View>;
  Text: AnimatedComponent<typeof Text>;
  Image: AnimatedComponent<typeof Image>;
  ScrollView: AnimatedComponent<typeof ScrollView>;
  FlatList: AnimatedComponent<typeof FlatList>;
  SectionList: AnimatedComponent<typeof SectionList>;
};

createAnimatedComponent()

Creates animated versions of custom components.

Animated.createAnimatedComponent<T>(Component: T): T

Usage:

// Create custom animated component
const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);

function CustomAnimatedButton({ onPress, children }) {
  const scale = new Animated.Value(1);
  const opacity = new Animated.Value(1);

  const handlePressIn = () => {
    Animated.parallel([
      Animated.spring(scale, {
        toValue: 0.95,
        useNativeDriver: false
      }),
      Animated.timing(opacity, {
        toValue: 0.7,
        duration: 100,
        useNativeDriver: false
      })
    ]).start();
  };

  const handlePressOut = () => {
    Animated.parallel([
      Animated.spring(scale, {
        toValue: 1,
        useNativeDriver: false
      }),
      Animated.timing(opacity, {
        toValue: 1,
        duration: 100,
        useNativeDriver: false
      })
    ]).start();
  };

  return (
    <AnimatedTouchableOpacity
      onPress={onPress}
      onPressIn={handlePressIn}
      onPressOut={handlePressOut}
      style={{
        transform: [{ scale }],
        opacity
      }}
    >
      {children}
    </AnimatedTouchableOpacity>
  );
}

// Advanced custom component with multiple animated properties
const AnimatedGradientView = Animated.createAnimatedComponent(
  ({ colors, style, children, ...props }) => (
    <View
      {...props}
      style={[
        {
          background: `linear-gradient(45deg, ${colors.join(', ')})`
        },
        style
      ]}
    >
      {children}
    </View>
  )
);

Interpolation

Transform animated values into different ranges and types for versatile property mapping.

animatedValue.interpolate({
  inputRange: number[];
  outputRange: (number | string)[];
  easing?: EasingFunction;
  extrapolate?: 'extend' | 'identity' | 'clamp';
  extrapolateLeft?: 'extend' | 'identity' | 'clamp';
  extrapolateRight?: 'extend' | 'identity' | 'clamp';
}): AnimatedInterpolation

Usage:

// Color interpolation
function ColorTransition() {
  const animatedValue = new Animated.Value(0);

  const backgroundColor = animatedValue.interpolate({
    inputRange: [0, 0.5, 1],
    outputRange: ['#ff0000', '#ffff00', '#00ff00']
  });

  const textColor = animatedValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['rgba(255,255,255,1)', 'rgba(0,0,0,1)']
  });

  return (
    <Animated.View style={{ backgroundColor }}>
      <Animated.Text style={{ color: textColor }}>
        Color Transition
      </Animated.Text>
    </Animated.View>
  );
}

// Multi-property interpolation
function ComplexInterpolation() {
  const scrollY = new Animated.Value(0);

  // Multiple interpolated properties from single value
  const headerOpacity = scrollY.interpolate({
    inputRange: [0, 50, 100],
    outputRange: [1, 0.5, 0],
    extrapolate: 'clamp'
  });

  const headerScale = scrollY.interpolate({
    inputRange: [0, 100],
    outputRange: [1, 0.8],
    extrapolate: 'clamp'
  });

  const titleFontSize = scrollY.interpolate({
    inputRange: [0, 100],
    outputRange: [24, 18],
    extrapolate: 'clamp'
  });

  const borderRadius = scrollY.interpolate({
    inputRange: [0, 50],
    outputRange: [0, 15],
    extrapolate: 'clamp'
  });

  return (
    <Animated.View
      style={{
        opacity: headerOpacity,
        transform: [{ scale: headerScale }],
        borderRadius
      }}
    >
      <Animated.Text
        style={{
          fontSize: titleFontSize
        }}
      >
        Dynamic Header
      </Animated.Text>
    </Animated.View>
  );
}

Web-Specific Implementation

React Native Web's Animated implementation provides full compatibility with React Native's API while leveraging web-native CSS transitions and transforms for optimal performance.

Key Features:

  • CSS-based animations for better performance
  • Hardware acceleration through CSS transforms
  • Full interpolation support including colors and complex values
  • Event-driven animations with Animated.event()
  • Composition and mathematical operations
  • Support for custom easing functions

Performance Notes:

  • Transform animations (translateX, scale, rotate) are hardware accelerated
  • Opacity animations perform well across all browsers
  • Color interpolations are computed in JavaScript
  • Large numbers of simultaneous animations may impact performance
  • Consider using useNativeDriver: true for transform and opacity animations when available

Types

interface CompositeAnimation {
  start(callback?: EndCallback): void;
  stop(): void;
  reset(): void;
  _startNativeLoop(iterations?: number): void;
  _isUsingNativeDriver(): boolean;
}

interface AnimatedValueConfig {
  useNativeDriver?: boolean;
}

interface TimingAnimationConfig {
  toValue: number | AnimatedValue;
  duration?: number;
  easing?: EasingFunction;
  delay?: number;
  useNativeDriver?: boolean;
  onComplete?: (result: EndResult) => void;
}

interface SpringAnimationConfig {
  toValue: number | AnimatedValue;
  restDisplacementThreshold?: number;
  restSpeedThreshold?: number;
  velocity?: number;
  bounciness?: number;
  speed?: number;
  tension?: number;
  friction?: number;
  stiffness?: number;
  damping?: number;
  mass?: number;
  useNativeDriver?: boolean;
  onComplete?: (result: EndResult) => void;
}

interface DecayAnimationConfig {
  velocity: number;
  deceleration?: number;
  useNativeDriver?: boolean;
  onComplete?: (result: EndResult) => void;
}

interface ParallelConfig {
  stopTogether?: boolean;
}

interface LoopAnimationConfig {
  iterations?: number;
  resetBeforeIteration?: boolean;
}

interface InterpolationConfigType {
  inputRange: number[];
  outputRange: (number | string)[];
  easing?: EasingFunction;
  extrapolate?: 'extend' | 'identity' | 'clamp';
  extrapolateLeft?: 'extend' | 'identity' | 'clamp';
  extrapolateRight?: 'extend' | 'identity' | 'clamp';
}

interface EndResult {
  finished: boolean;
}

type EndCallback = (result: EndResult) => void;
type ValueListenerCallback = (state: { value: number }) => void;
type ValueXYListenerCallback = (state: { value: { x: number; y: number } }) => void;

type Mapping = { [key: string]: any } | AnimatedValue | null;

interface EventConfig {
  useNativeDriver?: boolean;
  listener?: Function;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-native-web

docs

accessibility.md

animation.md

core-utilities.md

form-controls.md

hooks.md

index.md

interactive-components.md

layout-components.md

list-components.md

media-components.md

platform-apis.md

stylesheet.md

system-integration.md

text-input.md

tile.json