Skip to content

Commit 6611f22

Browse files
authored
Feat/new pan view improve animations (#1574)
* Small refactor and remove some code * Move useHiddenLocation * Use useHiddenLocation to improve animation * Rename springBack to animateToStart * Change RNView to View in the component * Rename animateToStart to animateToOrigin
1 parent 351742b commit 6611f22

File tree

11 files changed

+35
-39
lines changed

11 files changed

+35
-39
lines changed

demo/src/screens/incubatorScreens/PanViewScreen.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class PanViewScreen extends Component {
8080
<PanView
8181
directions={[PanView.directions.DOWN]}
8282
dismissible
83-
springBack
83+
animateToOrigin
8484
// threshold={{y: 10}}
8585
containerStyle={styles.panView}
8686
onDismiss={this.onDialogDismissed}
@@ -113,7 +113,7 @@ class PanViewScreen extends Component {
113113
<PanView
114114
directions={[PanView.directions.LEFT, PanView.directions.DOWN, PanView.directions.RIGHT]}
115115
dismissible
116-
springBack
116+
animateToOrigin
117117
directionLock
118118
threshold={{y: 10}}
119119
containerStyle={styles.panView}

generatedTypes/src/incubator/TransitionView/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { PropsWithChildren } from 'react';
22
import { ViewProps } from '../../components/view';
33
import { ForwardRefInjectedProps } from '../../commons/new';
4-
import { Direction } from './useHiddenLocation';
4+
import { Direction } from '../hooks/useHiddenLocation';
55
import { TransitionViewAnimationType } from './useAnimationEndNotifier';
66
import { AnimatedTransitionProps } from './useAnimatedTransition';
77
export { Direction, TransitionViewAnimationType };

generatedTypes/src/incubator/TransitionView/useAnimatedTransition.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Direction, HiddenLocation } from './useHiddenLocation';
1+
import { Direction, HiddenLocation } from '../hooks/useHiddenLocation';
22
import { AnimationNotifierEndProps } from './useAnimationEndNotifier';
33
export interface AnimatedTransitionProps extends AnimationNotifierEndProps {
44
/**

generatedTypes/src/incubator/TransitionView/useAnimatedTranslator.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Direction } from './useHiddenLocation';
1+
import { Direction } from '../hooks/useHiddenLocation';
22
export interface TranslatorProps {
33
initialVisibility: boolean;
44
}

generatedTypes/src/incubator/panView/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export interface PanViewProps extends ViewProps {
1616
/**
1717
* Animate to start if not dismissed.
1818
*/
19-
springBack?: boolean;
19+
animateToOrigin?: boolean;
2020
/**
2121
* Callback to the dismiss animation end
2222
*/

src/incubator/TransitionView/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {View as RNView, LayoutChangeEvent} from 'react-native';
33
import Animated from 'react-native-reanimated';
44
import View, {ViewProps} from '../../components/view';
55
import {forwardRef, ForwardRefInjectedProps} from '../../commons/new';
6-
import useHiddenLocation, {Direction} from './useHiddenLocation';
6+
import useHiddenLocation, {Direction} from '../hooks/useHiddenLocation';
77
import {TransitionViewAnimationType} from './useAnimationEndNotifier';
88
import useAnimatedTransition, {AnimatedTransitionProps} from './useAnimatedTransition';
99
const AnimatedView = Animated.createAnimatedComponent(View);

src/incubator/TransitionView/useAnimatedTransition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable react-hooks/exhaustive-deps */
22
import {useEffect, useCallback} from 'react';
3-
import {Direction, HiddenLocation} from './useHiddenLocation';
3+
import {Direction, HiddenLocation} from '../hooks/useHiddenLocation';
44
import useAnimatedTranslator from './useAnimatedTranslator';
55
import useAnimationEndNotifier, {AnimationNotifierEndProps} from './useAnimationEndNotifier';
66

src/incubator/TransitionView/useAnimatedTranslator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {useCallback} from 'react';
22
import {useSharedValue, useAnimatedStyle, withSpring, withTiming} from 'react-native-reanimated';
3-
import {Direction} from './useHiddenLocation';
3+
import {Direction} from '../hooks/useHiddenLocation';
44

55
export interface TranslatorProps {
66
initialVisibility: boolean;

src/incubator/panView/index.tsx

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import {isEmpty} from 'lodash';
22
import React, {useCallback} from 'react';
3-
import {StyleProp, ViewStyle} from 'react-native';
3+
import {StyleProp, View as RNView, ViewStyle} from 'react-native';
44
import {PanGestureHandler, PanGestureHandlerEventPayload} from 'react-native-gesture-handler';
55
import Animated, {
66
useSharedValue,
77
useAnimatedStyle,
88
withSpring,
9+
withTiming,
910
useAnimatedGestureHandler,
1011
runOnJS
1112
} from 'react-native-reanimated';
1213
import {asBaseComponent} from '../../commons/new';
13-
import {Constants} from '../../helpers';
1414
import View, {ViewProps} from '../../components/view';
1515
import {
1616
PanViewDirections,
@@ -20,6 +20,7 @@ import {
2020
getDismissVelocity,
2121
DEFAULT_THRESHOLD
2222
} from './panningUtil';
23+
import useHiddenLocation from '../hooks/useHiddenLocation';
2324
export {PanViewDirections, PanViewDismissThreshold};
2425

2526
export interface PanViewProps extends ViewProps {
@@ -35,7 +36,7 @@ export interface PanViewProps extends ViewProps {
3536
/**
3637
* Animate to start if not dismissed.
3738
*/
38-
springBack?: boolean;
39+
animateToOrigin?: boolean;
3940
/**
4041
* Callback to the dismiss animation end
4142
*/
@@ -64,7 +65,7 @@ const PanView = (props: Props) => {
6465
const {
6566
directions = [PanViewDirections.UP, PanViewDirections.DOWN, PanViewDirections.LEFT, PanViewDirections.RIGHT],
6667
dismissible,
67-
springBack,
68+
animateToOrigin,
6869
onDismiss,
6970
directionLock,
7071
threshold,
@@ -82,6 +83,9 @@ const PanView = (props: Props) => {
8283
};
8384
}, []);
8485

86+
const containerRef = React.createRef<RNView>();
87+
const {onLayout, hiddenLocation} = useHiddenLocation({containerRef});
88+
8589
const getTranslationOptions = () => {
8690
'worklet';
8791
return {
@@ -105,27 +109,17 @@ const PanView = (props: Props) => {
105109
runOnJS(onDismiss)();
106110
}
107111
},
112+
// eslint-disable-next-line react-hooks/exhaustive-deps
108113
[onDismiss]);
109114

110-
const shouldDismissX = useCallback((isFinished: boolean) => {
111-
'worklet';
112-
dismiss(isFinished);
113-
},
114-
[dismiss]);
115-
116-
const shouldDismissY = useCallback((isFinished: boolean) => {
115+
const returnToOrigin = useCallback(() => {
117116
'worklet';
118-
dismiss(isFinished);
119-
},
120-
[dismiss]);
121-
122-
const springBackIfNeeded = useCallback(() => {
123-
'worklet';
124-
if (springBack) {
117+
if (animateToOrigin) {
125118
translationX.value = withSpring(0, SPRING_BACK_ANIMATION_CONFIG);
126119
translationY.value = withSpring(0, SPRING_BACK_ANIMATION_CONFIG);
127120
}
128-
}, [springBack]);
121+
// eslint-disable-next-line react-hooks/exhaustive-deps
122+
}, [animateToOrigin]);
129123

130124
const onGestureEvent = useAnimatedGestureHandler({
131125
onStart: (_event: PanGestureHandlerEventPayload, context: {initialTranslation: Frame}) => {
@@ -139,28 +133,30 @@ const PanView = (props: Props) => {
139133
const velocity = getDismissVelocity(event, directions, getTranslationOptions(), threshold);
140134
if (velocity) {
141135
waitingForDismiss.value = true;
142-
if (velocity.x !== 0) {
143-
const toX = Math.sign(translationX.value) * (Math.abs(translationX.value) + Constants.screenWidth);
144-
translationX.value = withSpring(toX, {velocity: velocity.x, damping: 50}, shouldDismissX);
136+
if (translationX.value !== 0 && velocity.x !== undefined && velocity.x !== 0) {
137+
const toX = velocity.x > 0 ? hiddenLocation.right : hiddenLocation.left;
138+
const duration = Math.abs((toX - translationX.value) / velocity.x) * 1000;
139+
translationX.value = withTiming(toX, {duration}, dismiss);
145140
}
146-
if (velocity.y !== 0) {
147-
const toY = Math.sign(translationY.value) * (Math.abs(translationY.value) + Constants.screenHeight);
148-
translationY.value = withSpring(toY, {velocity: velocity.y, damping: 50}, shouldDismissY);
141+
142+
if (translationY.value !== 0 && velocity.y !== undefined && velocity.y !== 0) {
143+
const toY = velocity.y > 0 ? hiddenLocation.bottom : hiddenLocation.top;
144+
const duration = Math.abs((toY - translationY.value) / velocity.y) * 1000;
145+
translationY.value = withTiming(toY, {duration}, dismiss);
149146
}
150147
} else {
151-
springBackIfNeeded();
148+
returnToOrigin();
152149
}
153150
} else {
154-
springBackIfNeeded();
151+
returnToOrigin();
155152
}
156153
}
157154
},
158-
[directions, dismissible, setTranslation, springBackIfNeeded]);
155+
[directions, dismissible, setTranslation, returnToOrigin]);
159156

160157
return (
161158
// TODO: delete comments once completed
162-
// <View ref={containerRef} style={containerStyle} onLayout={onLayout}>
163-
<View style={containerStyle}>
159+
<View ref={containerRef} style={containerStyle} onLayout={onLayout}>
164160
<PanGestureHandler onGestureEvent={isEmpty(directions) ? undefined : onGestureEvent}>
165161
<Animated.View
166162
// !visible.current && styles.hidden is done to fix a bug is iOS

0 commit comments

Comments
 (0)