@@ -3,6 +3,7 @@ import { Gesture } from 'react-native-gesture-handler';
33import {
44 interpolate ,
55 useAnimatedStyle ,
6+ useDerivedValue ,
67 useSharedValue ,
78 withTiming ,
89} from 'react-native-reanimated' ;
@@ -14,6 +15,7 @@ import {
1415 getAnimationValueProperty ,
1516 getStyleTransform ,
1617} from '../../helpers/utils/animation' ;
18+ import { BASE_RIPPLE_PROGRESS_DURATION } from './pressable-feedback.constants' ;
1719import type {
1820 PressableFeedbackAnimation ,
1921 PressableFeedbackAnimationContextValue ,
@@ -48,7 +50,7 @@ export function usePressableFeedbackRootAnimation(options: {
4850 const scaleValue = getAnimationValueProperty ( {
4951 animationValue : animationConfig ?. scale ,
5052 property : 'value' ,
51- defaultValue : 0.99 ,
53+ defaultValue : 0.98 ,
5254 } ) ;
5355
5456 const scaleTimingConfig = getAnimationValueMergedConfig ( {
@@ -57,6 +59,41 @@ export function usePressableFeedbackRootAnimation(options: {
5759 defaultValue : { duration : 200 } ,
5860 } ) ;
5961
62+ const ignoreScaleCoefficient = getAnimationValueProperty ( {
63+ animationValue : animationConfig ?. scale ,
64+ property : 'ignoreScaleCoefficient' ,
65+ defaultValue : false ,
66+ } ) ;
67+
68+ // Ripple progress animation values
69+ const rippleProgressBaseDuration = getAnimationValueProperty ( {
70+ animationValue :
71+ variant === 'ripple'
72+ ? (
73+ animationConfig as Extract <
74+ PressableFeedbackRippleRootAnimation ,
75+ Record < string , any >
76+ >
77+ ) ?. ripple ?. progress
78+ : undefined ,
79+ property : 'baseDuration' ,
80+ defaultValue : BASE_RIPPLE_PROGRESS_DURATION ,
81+ } ) ;
82+
83+ const ignoreDurationCoefficient = getAnimationValueProperty ( {
84+ animationValue :
85+ variant === 'ripple'
86+ ? (
87+ animationConfig as Extract <
88+ PressableFeedbackRippleRootAnimation ,
89+ Record < string , any >
90+ >
91+ ) ?. ripple ?. progress
92+ : undefined ,
93+ property : 'ignoreDurationCoefficient' ,
94+ defaultValue : false ,
95+ } ) ;
96+
6097 // Shared values
6198 const isPressed = useSharedValue ( false ) ;
6299 const scale = useSharedValue ( 0 ) ;
@@ -66,6 +103,19 @@ export function usePressableFeedbackRootAnimation(options: {
66103 const containerHeight = useSharedValue ( 0 ) ;
67104 const rippleProgress = useSharedValue ( 0 ) ;
68105
106+ // Calculate duration coefficient based on diagonal to maintain consistent ripple speed
107+ // across different container sizes. Base diagonal is 450px.
108+ // Can be disabled by setting ignoreDurationCoefficient to true.
109+ const durationCoefficient = useDerivedValue ( ( ) => {
110+ if ( ignoreDurationCoefficient ) return 1 ;
111+
112+ const baseDiagonal = 450 ;
113+ const currentDiagonal = Math . sqrt (
114+ containerWidth . get ( ) ** 2 + containerHeight . get ( ) ** 2
115+ ) ;
116+ return currentDiagonal > 0 ? currentDiagonal / baseDiagonal : 1 ;
117+ } ) ;
118+
69119 // Gesture handling
70120 const gesture = Gesture . Pan ( )
71121 . onBegin ( ( event ) => {
@@ -78,7 +128,11 @@ export function usePressableFeedbackRootAnimation(options: {
78128 pressedCenterX . set ( event . x ) ;
79129 pressedCenterY . set ( event . y ) ;
80130 if ( rippleProgress . get ( ) === 0 ) {
81- rippleProgress . set ( withTiming ( 1 , { duration : 250 } ) ) ;
131+ const adjustedDuration = Math . min (
132+ rippleProgressBaseDuration * durationCoefficient . get ( ) ,
133+ rippleProgressBaseDuration * 2
134+ ) ;
135+ rippleProgress . set ( withTiming ( 1 , { duration : adjustedDuration } ) ) ;
82136 }
83137 } )
84138 . onFinalize ( ( ) => {
@@ -87,15 +141,23 @@ export function usePressableFeedbackRootAnimation(options: {
87141
88142 if ( variant === 'highlight' ) return ;
89143
90- rippleProgress . set ( withTiming ( 2 , { duration : 400 } ) ) ;
144+ const adjustedDuration = Math . min (
145+ rippleProgressBaseDuration * durationCoefficient . get ( ) ,
146+ rippleProgressBaseDuration * 2
147+ ) ;
148+ rippleProgress . set ( withTiming ( 2 , { duration : adjustedDuration } ) ) ;
91149 } ) ;
92150
93151 const styleTransform = getStyleTransform ( style ) ;
94152
95153 const rContainerStyle = useAnimatedStyle ( ( ) => {
96- const baseWidth = 300 ;
97- const coefficient =
98- containerWidth . get ( ) > 0 ? baseWidth / containerWidth . get ( ) : 1 ;
154+ // Calculate scale coefficient to maintain consistent scale effect across different sizes
155+ // Can be disabled by setting ignoreScaleCoefficient to true
156+ const coefficient = ignoreScaleCoefficient
157+ ? 1
158+ : containerWidth . get ( ) > 0
159+ ? 300 / containerWidth . get ( )
160+ : 1 ;
99161 const adjustedScaleValue = 1 - ( 1 - scaleValue ) * coefficient ;
100162
101163 if ( isAnimationDisabled ) {
0 commit comments