UNPKG

react-native-screen-transitions

Version:
85 lines (75 loc) 3.48 kB
"use strict"; import { clamp } from "react-native-reanimated"; const MAX_VELOCITY_MAGNITUDE = 3.2; const NEAR_ZERO_THRESHOLD = 0.01; /** * Converts velocity from pixels/second to normalized units/second (0-1 range) * and caps the result for stability */ const normalize = (velocityPixelsPerSecond, screenSize) => { "worklet"; return clamp(velocityPixelsPerSecond / Math.max(1, screenSize), -MAX_VELOCITY_MAGNITUDE, MAX_VELOCITY_MAGNITUDE); }; /** * Calculates a normalized velocity that moves the current value toward zero. * Used for spring-back animations when dismissing gestures. */ const calculateRestoreVelocity = (currentValueNormalized, baseVelocityNormalized) => { "worklet"; if (Math.abs(currentValueNormalized) < NEAR_ZERO_THRESHOLD) return 0; const directionTowardZero = Math.sign(currentValueNormalized) || 1; const clampedVelocity = Math.min(Math.abs(baseVelocityNormalized), 1); return -directionTowardZero * clampedVelocity; }; const calculateProgressVelocity = ({ animations, shouldDismiss, event, dimensions, directions }) => { "worklet"; const currentProgress = animations.progress.value; const targetProgress = shouldDismiss ? 0 : 1; const progressDelta = targetProgress - currentProgress; const progressDirection = progressDelta === 0 ? 0 : Math.sign(progressDelta); const normalizedVelocityX = normalize(event.velocityX, dimensions.width); const normalizedVelocityY = normalize(event.velocityY, dimensions.height); const normalizedTranslationX = Math.abs(event.translationX / dimensions.width); const normalizedTranslationY = Math.abs(event.translationY / dimensions.height); const supportsHorizontalGestures = directions.horizontal || directions.horizontalInverted; const supportsVerticalGestures = directions.vertical || directions.verticalInverted; let progressVelocityMagnitude = 0; // Determine which axis should drive the progress velocity if (supportsHorizontalGestures && (!supportsVerticalGestures || normalizedTranslationX >= normalizedTranslationY)) { progressVelocityMagnitude = Math.abs(normalizedVelocityX); } else if (supportsVerticalGestures) { progressVelocityMagnitude = Math.abs(normalizedVelocityY); } else { progressVelocityMagnitude = Math.max(Math.abs(normalizedVelocityX), Math.abs(normalizedVelocityY)); } // Apply direction and clamp to prevent overly energetic springs return progressDirection * clamp(progressVelocityMagnitude, 0, MAX_VELOCITY_MAGNITUDE); }; /** * Determines if a gesture should trigger dismissal based on combined * translation and velocity in normalized screen units (0-1 range). * * Formula: |translation/screen + clamp(velocity/screen, ±1) * velocityWeight| > 0.5 */ const shouldPassDismissalThreshold = (translationPixels, velocityPixelsPerSecond, screenSize, velocityWeight) => { "worklet"; const normalizedTranslation = translationPixels / Math.max(1, screenSize); const normalizedVelocity = normalize(velocityPixelsPerSecond, screenSize); const projectedNormalizedPosition = normalizedTranslation + normalizedVelocity * velocityWeight; const exceedsThreshold = Math.abs(projectedNormalizedPosition) > 0.5; const hasMovement = translationPixels !== 0 || velocityPixelsPerSecond !== 0; return exceedsThreshold && hasMovement; }; export const velocity = { normalize, calculateRestoreVelocity, calculateProgressVelocity, shouldPassDismissalThreshold }; //# sourceMappingURL=velocity.js.map