CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-reanimated

More powerful alternative to Animated library for React Native with UI thread animations and advanced gesture handling.

Pending
Overview
Eval results
Files

platform-functions.mddocs/

Platform Functions

Utilities for measuring components, scrolling, native platform integration, and accessing platform-specific functionality for optimal performance and native behavior.

Capabilities

Component Measurement

Functions for measuring component dimensions and positions.

/**
 * Measures the dimensions and position of a component
 * @param ref - Animated ref to the component to measure
 * @returns MeasuredDimensions object or null if measurement fails
 */
function measure(ref: AnimatedRef<any>): MeasuredDimensions | null;

/**
 * Gets relative coordinates within a component
 * @param ref - Animated ref to the reference component
 * @param x - X coordinate to convert
 * @param y - Y coordinate to convert
 * @returns ComponentCoords object or null if conversion fails
 */
function getRelativeCoords(
  ref: AnimatedRef<any>, 
  x: number, 
  y: number
): ComponentCoords | null;

interface MeasuredDimensions {
  /** Component x position relative to its parent */
  x: number;
  /** Component y position relative to its parent */
  y: number;
  /** Component width */
  width: number;
  /** Component height */
  height: number;
  /** Component x position relative to the screen */
  pageX: number;
  /** Component y position relative to the screen */
  pageY: number;
}

interface ComponentCoords {
  /** X coordinate relative to the component */
  x: number;
  /** Y coordinate relative to the component */
  y: number;
}

Usage Examples:

import React, { useRef } from "react";
import Animated, {
  useAnimatedRef,
  measure,
  getRelativeCoords,
  useSharedValue,
  useAnimatedStyle,
  runOnUI,
  runOnJS
} from "react-native-reanimated";
import { Button } from "react-native";

const MeasurementExample = () => {
  const containerRef = useAnimatedRef();
  const targetRef = useAnimatedRef();
  const ballPosition = useSharedValue({ x: 50, y: 50 });

  // Measure component dimensions
  const measureComponent = () => {
    runOnUI(() => {
      'worklet';
      const dimensions = measure(targetRef);
      if (dimensions) {
        runOnJS(console.log)('Component dimensions:', dimensions);
        // Use measurements for animations
        ballPosition.value = {
          x: dimensions.width / 2,
          y: dimensions.height / 2
        };
      }
    })();
  };

  // Convert screen coordinates to component-relative coordinates
  const handlePress = (event: any) => {
    const { locationX, locationY } = event.nativeEvent;
    
    runOnUI(() => {
      'worklet';
      const coords = getRelativeCoords(containerRef, locationX, locationY);
      if (coords) {
        ballPosition.value = coords;
        runOnJS(console.log)('Relative coordinates:', coords);
      }
    })();
  };

  const ballStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: ballPosition.value.x - 25 }, // Center the ball
      { translateY: ballPosition.value.y - 25 },
    ],
  }));

  return (
    <>
      <Button title="Measure Target" onPress={measureComponent} />
      
      <Animated.View
        ref={containerRef}
        onTouchEnd={handlePress}
        style={{
          width: 300,
          height: 200,
          backgroundColor: "lightgray",
          margin: 20,
          borderRadius: 10,
          position: "relative",
        }}
      >
        <Animated.Text>Touch anywhere to move the ball</Animated.Text>
        
        {/* Target component to measure */}
        <Animated.View
          ref={targetRef}
          style={{
            width: 100,
            height: 100,
            backgroundColor: "lightblue",
            position: "absolute",
            top: 20,
            right: 20,
            borderRadius: 5,
          }}
        >
          <Animated.Text>Target</Animated.Text>
        </Animated.View>

        {/* Animated ball */}
        <Animated.View
          style={[
            {
              width: 50,
              height: 50,
              backgroundColor: "red",
              borderRadius: 25,
              position: "absolute",
            },
            ballStyle,
          ]}
        />
      </Animated.View>
    </>
  );
};

Scrolling Control

Programmatic scrolling control for ScrollView and other scrollable components.

/**
 * Programmatically scrolls a scrollable component
 * @param ref - Animated ref to the scrollable component
 * @param x - X coordinate to scroll to
 * @param y - Y coordinate to scroll to
 * @param animated - Whether to animate the scroll
 */
function scrollTo(
  ref: AnimatedRef<any>,
  x: number,
  y: number,
  animated: boolean
): void;

Usage Examples:

import React from "react";
import Animated, {
  useAnimatedRef,
  scrollTo,
  useSharedValue,
  useAnimatedScrollHandler,
  runOnUI
} from "react-native-reanimated";
import { Button } from "react-native";

const ScrollControlExample = () => {
  const scrollRef = useAnimatedRef();
  const scrollY = useSharedValue(0);

  // Track scroll position
  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      scrollY.value = event.contentOffset.y;
    },
  });

  // Scroll to specific positions
  const scrollToTop = () => {
    runOnUI(() => {
      'worklet';
      scrollTo(scrollRef, 0, 0, true);
    })();
  };

  const scrollToMiddle = () => {
    runOnUI(() => {
      'worklet';
      scrollTo(scrollRef, 0, 500, true);
    })();
  };

  const scrollToBottom = () => {
    runOnUI(() => {
      'worklet';
      scrollTo(scrollRef, 0, 1500, true);
    })();
  };

  // Smooth scrolling animation
  const smoothScrollTo = (targetY: number) => {
    runOnUI(() => {
      'worklet';
      const startY = scrollY.value;
      const distance = targetY - startY;
      const duration = Math.abs(distance) / 2; // Adjust speed based on distance
      
      // Custom smooth scroll implementation
      const startTime = Date.now();
      const animate = () => {
        'worklet';
        const elapsed = Date.now() - startTime;
        const progress = Math.min(elapsed / duration, 1);
        const easeProgress = 1 - Math.pow(1 - progress, 3); // Ease out cubic
        
        const currentY = startY + distance * easeProgress;
        scrollTo(scrollRef, 0, currentY, false);
        
        if (progress < 1) {
          // Continue animation
          setTimeout(() => animate(), 16); // ~60fps
        }
      };
      
      animate();
    })();
  };

  return (
    <>
      <Button title="Scroll to Top" onPress={scrollToTop} />
      <Button title="Scroll to Middle" onPress={scrollToMiddle} />
      <Button title="Scroll to Bottom" onPress={scrollToBottom} />
      <Button title="Smooth Scroll to 800" onPress={() => smoothScrollTo(800)} />

      <Animated.ScrollView
        ref={scrollRef}
        onScroll={scrollHandler}
        scrollEventThrottle={16}
        style={{ height: 400 }}
      >
        {/* Content to scroll through */}
        {Array.from({ length: 100 }).map((_, index) => (
          <Animated.View
            key={index}
            style={{
              height: 60,
              backgroundColor: index % 2 ? "white" : "lightgray",
              justifyContent: "center",
              alignItems: "center",
              borderBottomWidth: 1,
              borderBottomColor: "gray",
            }}
          >
            <Animated.Text>Item {index} - Y: {index * 60}</Animated.Text>
          </Animated.View>
        ))}
      </Animated.ScrollView>
    </>
  );
};

Native Props Manipulation

Direct manipulation of native component properties for performance-critical updates.

/**
 * Sets native properties on a component directly
 * @param ref - Animated ref to the component
 * @param props - Object containing properties to set
 */
function setNativeProps(ref: AnimatedRef<any>, props: object): void;

/**
 * Dispatches a command to a native component
 * @param ref - Animated ref to the component
 * @param commandName - Name of the command to dispatch
 * @param args - Optional arguments for the command
 */
function dispatchCommand(
  ref: AnimatedRef<any>,
  commandName: string,
  args?: any[]
): void;

/**
 * Gets a property value from a native component
 * @param ref - Animated ref to the component
 * @param prop - Property name to get
 * @returns Property value
 */
function getViewProp(ref: AnimatedRef<any>, prop: string): any;

Usage Examples:

import React from "react";
import { TextInput } from "react-native";
import Animated, {
  useAnimatedRef,
  setNativeProps,
  dispatchCommand,
  getViewProp,
  useSharedValue,
  useAnimatedStyle,
  runOnUI,
  runOnJS
} from "react-native-reanimated";
import { Button } from "react-native";

const NativePropsExample = () => {
  const textInputRef = useAnimatedRef();
  const viewRef = useAnimatedRef();
  const opacity = useSharedValue(1);

  // Direct native prop manipulation
  const changeInputProps = () => {
    runOnUI(() => {
      'worklet';
      setNativeProps(textInputRef, {
        text: "Updated via native props!",
        placeholder: "Native update",
        backgroundColor: "#ffeeee",
      });
    })();
  };

  // Focus input using dispatch command
  const focusInput = () => {
    runOnUI(() => {
      'worklet';
      dispatchCommand(textInputRef, "focus", []);
    })();
  };

  // Blur input using dispatch command
  const blurInput = () => {
    runOnUI(() => {
      'worklet';
      dispatchCommand(textInputRef, "blur", []);
    })();
  };

  // Get view properties
  const getViewProperties = () => {
    runOnUI(() => {
      'worklet';
      const opacity = getViewProp(viewRef, "opacity");
      const backgroundColor = getViewProp(viewRef, "backgroundColor");
      
      runOnJS(console.log)("View opacity:", opacity);
      runOnJS(console.log)("View backgroundColor:", backgroundColor);
    })();
  };

  // Batch native updates for performance
  const batchNativeUpdates = () => {
    runOnUI(() => {
      'worklet';
      // Multiple native updates in single UI frame
      setNativeProps(viewRef, {
        backgroundColor: `hsl(${Math.random() * 360}, 70%, 80%)`,
        borderRadius: Math.random() * 20,
        borderWidth: Math.random() * 5,
      });
      
      setNativeProps(textInputRef, {
        fontSize: 14 + Math.random() * 10,
        color: Math.random() > 0.5 ? "black" : "blue",
      });
    })();
  };

  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
  }));

  return (
    <>
      <Button title="Change Input Props" onPress={changeInputProps} />
      <Button title="Focus Input" onPress={focusInput} />
      <Button title="Blur Input" onPress={blurInput} />
      <Button title="Get View Props" onPress={getViewProperties} />
      <Button title="Batch Updates" onPress={batchNativeUpdates} />

      <Animated.View
        ref={viewRef}
        style={[
          {
            width: 200,
            height: 100,
            backgroundColor: "lightblue",
            margin: 20,
            padding: 10,
            borderRadius: 10,
          },
          animatedStyle,
        ]}
      >
        <TextInput
          ref={textInputRef}
          style={{
            height: 40,
            borderWidth: 1,
            borderColor: "gray",
            borderRadius: 5,
            paddingHorizontal: 10,
            backgroundColor: "white",
          }}
          placeholder="Type something..."
        />
      </Animated.View>
    </>
  );
};

Gesture Integration

Integration with gesture handling systems for advanced touch interactions.

/**
 * Sets the state of a gesture handler
 * @param handlerTag - Tag identifying the gesture handler
 * @param newState - New state to set for the handler
 */
function setGestureState(handlerTag: number, newState: number): void;

Usage Example:

import React from "react";
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  setGestureState,
  runOnUI
} from "react-native-reanimated";
import { PanGestureHandler, State } from "react-native-gesture-handler";

const GestureIntegrationExample = () => {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);
  const gestureHandlerTag = useSharedValue(0);

  // Gesture handler with state control
  const gestureHandler = useAnimatedGestureHandler({
    onStart: (_, context) => {
      context.startX = translateX.value;
      context.startY = translateY.value;
    },
    onActive: (event, context) => {
      translateX.value = context.startX + event.translationX;
      translateY.value = context.startY + event.translationY;
      
      // Control gesture state based on conditions
      if (Math.abs(event.translationX) > 200) {
        // Cancel gesture if moved too far
        setGestureState(gestureHandlerTag.value, State.CANCELLED);
      }
    },
    onEnd: (event) => {
      // Snap back to center if released
      if (Math.abs(translateX.value) > 100 || Math.abs(translateY.value) > 100) {
        translateX.value = withSpring(0);
        translateY.value = withSpring(0);
      }
    },
  });

  // Programmatic gesture control
  const resetGesture = () => {
    runOnUI(() => {
      'worklet';
      setGestureState(gestureHandlerTag.value, State.END);
      translateX.value = withSpring(0);
      translateY.value = withSpring(0);
    })();
  };

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: translateX.value },
      { translateY: translateY.value },
    ],
  }));

  return (
    <>
      <Button title="Reset Gesture" onPress={resetGesture} />
      
      <PanGestureHandler
        onGestureEvent={gestureHandler}
        onHandlerStateChange={(event) => {
          gestureHandlerTag.value = event.nativeEvent.handlerTag;
        }}
      >
        <Animated.View
          style={[
            {
              width: 100,
              height: 100,
              backgroundColor: "lightcoral",
              borderRadius: 10,
              margin: 50,
            },
            animatedStyle,
          ]}
        >
          <Animated.Text style={{ textAlign: "center", marginTop: 35 }}>
            Drag me!
          </Animated.Text>
        </Animated.View>
      </PanGestureHandler>
    </>
  );
};

Platform-Specific Utilities

Utilities for handling platform differences and native integration.

Version and Configuration Checks:

import {
  isConfigured,
  isReanimated3,
  reanimatedVersion
} from "react-native-reanimated";

// Check if Reanimated is properly configured
if (isConfigured()) {
  console.log("Reanimated is ready");
}

// Check version
if (isReanimated3()) {
  console.log("Using Reanimated 3+");
}

console.log("Reanimated version:", reanimatedVersion);

Configuration and Debugging:

import {
  configureReanimatedLogger,
  ReanimatedLogLevel,
  enableLayoutAnimations
} from "react-native-reanimated";

// Configure logging
configureReanimatedLogger({
  level: ReanimatedLogLevel.warn,
  strict: false,
});

// Enable layout animations (required for some platforms)
enableLayoutAnimations(true);

Performance Monitoring

Monitor and optimize animation performance using built-in tools.

/**
 * Performance monitoring component for tracking animation performance
 */
const PerformanceMonitor: React.ComponentType<PerformanceMonitorProps>;

interface PerformanceMonitorProps {
  /** Whether to show performance overlay */
  enabled?: boolean;
  /** Callback for performance data */
  onPerformanceData?: (data: PerformanceData) => void;
}

interface PerformanceData {
  /** Frames per second */
  fps: number;
  /** JavaScript thread usage */
  jsThreadUsage: number;
  /** UI thread usage */
  uiThreadUsage: number;
  /** Memory usage */
  memoryUsage: number;
}

Usage Example:

import React, { useState } from "react";
import Animated, { 
  PerformanceMonitor,
  useSharedValue,
  useAnimatedStyle,
  withRepeat,
  withTiming
} from "react-native-reanimated";

const PerformanceExample = () => {
  const [performanceEnabled, setPerformanceEnabled] = useState(false);
  const rotation = useSharedValue(0);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ rotate: `${rotation.value}deg` }],
  }));

  const startHeavyAnimation = () => {
    rotation.value = withRepeat(
      withTiming(360, { duration: 100 }),
      -1,
      false
    );
  };

  const handlePerformanceData = (data: PerformanceData) => {
    console.log("Performance:", data);
  };

  return (
    <>
      <PerformanceMonitor
        enabled={performanceEnabled}
        onPerformanceData={handlePerformanceData}
      />
      
      <Button 
        title={`Performance Monitor: ${performanceEnabled ? "ON" : "OFF"}`}
        onPress={() => setPerformanceEnabled(!performanceEnabled)}
      />
      
      <Button title="Start Heavy Animation" onPress={startHeavyAnimation} />
      
      <Animated.View
        style={[
          {
            width: 100,
            height: 100,
            backgroundColor: "lightgreen",
            margin: 20,
          },
          animatedStyle,
        ]}
      />
    </>
  );
};

Type Definitions

interface AnimatedRef<T> {
  current: T | null;
  (component?: T | null): void;
}

interface SerializableRef {
  __reanimatedSerializableRef: true;
  __value: number;
}

type NativeMethods = {
  measure(callback: (x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void): void;
  measureInWindow(callback: (x: number, y: number, width: number, height: number) => void): void;
  measureLayout(
    relativeToNativeNode: number,
    onSuccess: (left: number, top: number, width: number, height: number) => void,
    onFail: () => void
  ): void;
  setNativeProps(nativeProps: object): void;
  focus(): void;
  blur(): void;
};

enum ReanimatedLogLevel {
  debug = 0,
  info = 1,
  warn = 2,
  error = 3,
}

interface LoggerConfig {
  level?: ReanimatedLogLevel;
  strict?: boolean;
}

Best Practices

Performance Optimization

  1. Batch native updates: Group multiple setNativeProps calls together
  2. Use appropriate measurement timing: Measure after layout is complete
  3. Cache measurement results: Store dimensions in shared values when possible
  4. Minimize cross-thread communication: Keep measurements on UI thread when possible
  5. Profile with PerformanceMonitor: Monitor FPS and thread usage

Platform Considerations

  1. Test on all target platforms: iOS, Android, and Web have different behaviors
  2. Handle platform-specific features: Some functions may not be available on all platforms
  3. Use native props judiciously: Direct native manipulation bypasses React's reconciliation
  4. Consider accessibility: Ensure platform functions don't break accessibility features

Common Patterns

  1. Responsive layouts: Use measurements to create adaptive UIs
  2. Custom gesture handling: Combine with gesture libraries for complex interactions
  3. Performance monitoring: Track animation performance in development builds
  4. Smooth scrolling: Implement custom scroll behaviors with scrollTo

Install with Tessl CLI

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

docs

animated-components.md

animation-functions.md

configuration-utilities.md

core-reactive-system.md

css-integration.md

event-handling.md

index.md

interpolation-easing.md

layout-animations.md

platform-functions.md

screen-transitions.md

testing-utilities.md

worklet-functions.md

tile.json