rs-react-native-image-gallery
Version:
React Native Image Gallery with Thumbnails
89 lines (70 loc) • 2.71 kB
text/typescript
import { Image, type NativeTouchEvent } from 'react-native';
import { SCALE_MULTIPLIER } from './constants';
/**
* Calculate squared distance between two points
* @param a First coordinate
* @param b Second coordinate
*/
export const pow2abs = (a: number, b: number): number => (a - b) ** 2;
/**
* Get distance between two touch points
* @param touches Array of touch events
*/
export const getDistance = (touches: Array<NativeTouchEvent>): number => {
// Early validation
if (!touches || touches.length < 2) return 0;
const [a, b] = touches;
// Null check with optional chaining
if (!a?.pageX || !b?.pageX || !a?.pageY || !b?.pageY) return 0;
return Math.sqrt(pow2abs(a.pageX, b.pageX) + pow2abs(a.pageY, b.pageY));
};
// Cache for memoized distance calculations - improves performance on pinch gestures
const distanceCache = new Map<string, number>();
/**
* Memoized version of getDistance - caches results for better performance
* Only use this when you expect the same touch points to be calculated repeatedly
* @param touches Array of touch events
*/
export const getMemoizedDistance = (touches: Array<NativeTouchEvent>): number => {
// Early validation
if (!touches || touches.length < 2) return 0;
const [a, b] = touches;
// Null check with optional chaining
if (!a?.pageX || !b?.pageX || !a?.pageY || !b?.pageY) return 0;
// Create cache key from touch coordinates
const key = `${a.pageX},${a.pageY}-${b.pageX},${b.pageY}`;
if (distanceCache.has(key)) {
return distanceCache.get(key)!;
}
const distance = Math.sqrt(pow2abs(a.pageX, b.pageX) + pow2abs(a.pageY, b.pageY));
// Cache result - limit cache size to avoid memory leaks
if (distanceCache.size > 100) {
// Clear cache when it gets too big
distanceCache.clear();
}
distanceCache.set(key, distance);
return distance;
};
/**
* Calculate scale based on distance ratio with a multiplier
* @param currentDistance Current distance between touch points
* @param initialDistance Initial distance between touch points
*/
export const getScale = (currentDistance: number, initialDistance: number): number => {
// Prevent division by zero
if (!initialDistance) return 1;
return (currentDistance / initialDistance) * SCALE_MULTIPLIER;
};
/**
* Pre-loads images to avoid spinner issues
* @param urls Array of image URLs to preload (only URLs are supported for prefetch)
*/
export const preLoadImages = (urls: string[]): void => {
urls.forEach((url) => {
if (!url || typeof url !== 'string') return;
// Use Image.prefetch for native platforms (only works with URL strings)
Image.prefetch(url).catch(() => {
// Silent catch - we don't need to handle prefetch errors
});
});
};