Utility library for React Native Reanimated and Gesture Handler providing mathematical functions, animations, transformations, and helper utilities for building complex gesture-driven animations.
—
Coordinate system conversions between canvas, cartesian, and polar coordinate systems for advanced geometric calculations and animations.
/**
* Polar coordinate representation
*/
interface PolarPoint {
/** Angle in radians */
theta: number;
/** Distance from origin */
radius: number;
}Convert between canvas coordinates (origin top-left, Y increases downward) and mathematical cartesian coordinates (origin at center, Y increases upward).
/**
* Convert canvas coordinates to cartesian coordinates
* @param v - Canvas coordinate point
* @param center - Center point for coordinate system
* @returns Cartesian coordinate point
*/
function canvas2Cartesian(v: Vector, center: Vector): Vector;
/**
* Convert cartesian coordinates to canvas coordinates
* @param v - Cartesian coordinate point
* @param center - Center point for coordinate system
* @returns Canvas coordinate point
*/
function cartesian2Canvas(v: Vector, center: Vector): Vector;Usage Example:
import { canvas2Cartesian, cartesian2Canvas, vec2 } from "react-native-redash";
// Canvas setup
const screenWidth = 300;
const screenHeight = 400;
const center = vec2(screenWidth / 2, screenHeight / 2); // (150, 200)
// Convert touch position to mathematical coordinates
const touchPosition = vec2(100, 100); // Top-left area of screen
const mathCoords = canvas2Cartesian(touchPosition, center);
// Result: { x: -50, y: 100 } (left and up from center)
// Convert back to canvas for drawing
const canvasCoords = cartesian2Canvas(mathCoords, center);
// Result: { x: 100, y: 100 } (original position)Convert between cartesian (x, y) and polar (angle, radius) coordinate systems.
/**
* Convert cartesian coordinates to polar coordinates
* @param v - Cartesian coordinate point
* @returns Polar coordinate point
*/
function cartesian2Polar(v: Vector): PolarPoint;
/**
* Convert polar coordinates to cartesian coordinates
* @param p - Polar coordinate point
* @returns Cartesian coordinate point
*/
function polar2Cartesian(p: PolarPoint): Vector;Usage Example:
import { cartesian2Polar, polar2Cartesian, vec2 } from "react-native-redash";
// Convert point to polar coordinates
const point = vec2(100, 100);
const polar = cartesian2Polar(point);
// Result: { theta: 0.785..., radius: 141.42... } (45° at distance √2*100)
// Convert back to cartesian
const cartesian = polar2Cartesian(polar);
// Result: { x: 100, y: 100 } (original point)
// Useful for rotational animations
const rotatedPolar = { ...polar, theta: polar.theta + Math.PI / 4 };
const rotatedPoint = polar2Cartesian(rotatedPolar);Convenience functions that combine multiple coordinate system conversions.
/**
* Convert polar coordinates directly to canvas coordinates
* @param p - Polar coordinate point
* @param center - Canvas center point
* @returns Canvas coordinate point
*/
function polar2Canvas(p: PolarPoint, center: Vector): Vector;
/**
* Convert canvas coordinates directly to polar coordinates
* @param v - Canvas coordinate point
* @param center - Canvas center point
* @returns Polar coordinate point
*/
function canvas2Polar(v: Vector, center: Vector): PolarPoint;Complete Animation Example:
import React, { useEffect } from "react";
import { View, StyleSheet } from "react-native";
import {
canvas2Polar,
polar2Canvas,
canvas2Cartesian,
vec2,
useVector
} from "react-native-redash";
import Animated, {
useSharedValue,
useAnimatedStyle,
useAnimatedGestureHandler,
withSpring,
useDerivedValue,
withRepeat,
withTiming
} from "react-native-reanimated";
import { PanGestureHandler } from "react-native-gesture-handler";
export const PolarAnimationDemo = () => {
const center = vec2(150, 200);
const position = useVector(150, 200);
const angle = useSharedValue(0);
const radius = useSharedValue(80);
// Animate in circular motion
useEffect(() => {
angle.value = withRepeat(
withTiming(Math.PI * 2, { duration: 3000 }),
-1,
false
);
}, []);
// Convert polar to canvas coordinates for circular animation
const circularStyle = useAnimatedStyle(() => {
const canvasPos = polar2Canvas(
{ theta: angle.value, radius: radius.value },
center
);
return {
transform: [
{ translateX: canvasPos.x - 25 }, // Offset for element size
{ translateY: canvasPos.y - 25 }
]
};
});
// Gesture handler for interactive element
const gestureHandler = useAnimatedGestureHandler({
onActive: (event) => {
const touchPos = vec2(event.absoluteX, event.absoluteY);
const polar = canvas2Polar(touchPos, center);
// Update position based on polar coordinates
position.x.value = touchPos.x;
position.y.value = touchPos.y;
// Could use polar data for other effects
radius.value = withSpring(Math.min(polar.radius, 120));
}
});
const interactiveStyle = useAnimatedStyle(() => ({
transform: [
{ translateX: position.x.value - 25 },
{ translateY: position.y.value - 25 }
]
}));
// Polar coordinate display
const polarDisplay = useDerivedValue(() => {
const touchPos = vec2(position.x.value, position.y.value);
const polar = canvas2Polar(touchPos, center);
return `θ: ${(polar.theta * 180 / Math.PI).toFixed(1)}° r: ${polar.radius.toFixed(1)}`;
});
return (
<View style={styles.container}>
{/* Center point */}
<View style={[styles.center, {
left: center.x - 5,
top: center.y - 5
}]} />
{/* Circular animation */}
<Animated.View style={[styles.circle, circularStyle]} />
{/* Interactive element */}
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View style={[styles.interactive, interactiveStyle]} />
</PanGestureHandler>
{/* Coordinate display would go here in real app */}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f0f0f0"
},
center: {
position: "absolute",
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: "red"
},
circle: {
position: "absolute",
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: "blue"
},
interactive: {
position: "absolute",
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: "green"
}
});Practical Use Cases:
import {
canvas2Polar,
polar2Canvas,
cartesian2Polar,
polar2Cartesian,
vec2
} from "react-native-redash";
// 1. Radial menu positioning
const menuItems = 6;
const menuRadius = 100;
const center = vec2(150, 150);
const menuPositions = Array.from({ length: menuItems }, (_, i) => {
const angle = (i * 2 * Math.PI) / menuItems;
return polar2Canvas({ theta: angle, radius: menuRadius }, center);
});
// 2. Orbital animation
const orbitRadius = useSharedValue(80);
const orbitSpeed = useSharedValue(1);
const orbitStyle = useAnimatedStyle(() => {
const time = Date.now() / 1000;
const angle = time * orbitSpeed.value;
const position = polar2Canvas(
{ theta: angle, radius: orbitRadius.value },
center
);
return {
transform: [
{ translateX: position.x },
{ translateY: position.y }
]
};
});
// 3. Compass or gauge interfaces
const compassNeedle = useAnimatedStyle(() => {
const heading = heading.value; // Some heading value
const needleEnd = polar2Canvas(
{ theta: heading, radius: 80 },
center
);
// Calculate rotation for needle pointing to the coordinate
return {
transform: [
{ rotate: `${heading}rad` }
]
};
});Install with Tessl CLI
npx tessl i tessl/npm-react-native-redash