Created
April 21, 2020 11:26
-
-
Save iremlopsum/ae062b37017e8c29ce5857886c9344e3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable react/jsx-props-no-spreading */ | |
import React, { useRef, useCallback } from 'react' | |
import { | |
View, | |
StyleSheet, | |
TouchableOpacity, | |
GestureResponderEvent, | |
Dimensions, | |
} from 'react-native' | |
import { State, PanGestureHandler } from 'react-native-gesture-handler' | |
import { | |
useGestureHandler, | |
withSpring, | |
spring, | |
ReText, | |
} from 'react-native-redash' | |
import Animated, { Extrapolate } from 'react-native-reanimated' | |
const { | |
Value, | |
interpolate, | |
concat, | |
useCode, | |
cond, | |
block, | |
set, | |
Clock, | |
not, | |
clockRunning, | |
} = Animated | |
const SPRING_CONFIG = { | |
damping: 80, | |
mass: 4, | |
stiffness: 500, | |
overshootClamping: false, | |
restDisplacementThreshold: 0.001, | |
restSpeedThreshold: 0.001, | |
} | |
const { width: ww, height: wh } = Dimensions.get('window') | |
const Backdrop = ({ | |
onSetDrawerHidden, | |
translateX, | |
}: { | |
onSetDrawerHidden: ((event: GestureResponderEvent) => void) | undefined | |
translateX: Animated.Node<number> | |
}): JSX.Element => { | |
const opacity = interpolate(translateX, { | |
inputRange: [0, 250], | |
outputRange: [0, 0.6], | |
extrapolate: Extrapolate.CLAMP, | |
}) | |
return ( | |
<Animated.View style={StyleSheet.flatten([styles.backdrop, { opacity }])}> | |
<TouchableOpacity | |
style={StyleSheet.absoluteFillObject} | |
onPress={onSetDrawerHidden} | |
/> | |
</Animated.View> | |
) | |
} | |
const BurgerMenu = ({ | |
onSetDrawerActive, | |
}: { | |
onSetDrawerActive: ((event: GestureResponderEvent) => void) | undefined | |
}): JSX.Element => { | |
return ( | |
<TouchableOpacity style={styles.burgerButton} onPress={onSetDrawerActive}> | |
{/* <Icon icon="hamburger" size={24} color={colors.PRIMARY_BLUE} /> */} | |
</TouchableOpacity> | |
) | |
} | |
const Drawer = ({ | |
translateX, | |
}: { | |
translateX: Animated.Node<number> | |
}): JSX.Element => { | |
return ( | |
<Animated.View | |
style={StyleSheet.flatten([ | |
styles.drawer, | |
{ transform: [{ translateX }] }, | |
])} | |
/> | |
) | |
} | |
const App = (): JSX.Element => { | |
const openDrawerAnimatedState = useRef(new Animated.Value<0 | 1>(0)).current | |
const closeDrawerAnimatedState = useRef(new Animated.Value<0 | 1>(0)).current | |
const translationX = useRef(new Value(0)).current | |
const velocityX = useRef(new Value(0)).current | |
const state = useRef(new Value(State.UNDETERMINED)).current | |
const offset = useRef(new Value(0)).current | |
const gestureHandler = useGestureHandler({ translationX, velocityX, state }, [ | |
translationX, | |
velocityX, | |
state, | |
]) | |
const onSetDrawerActive = useCallback( | |
() => openDrawerAnimatedState.setValue(1), | |
[openDrawerAnimatedState], | |
) | |
const onSetDrawerHidden = useCallback( | |
() => closeDrawerAnimatedState.setValue(1), | |
[closeDrawerAnimatedState], | |
) | |
const translateX = withSpring({ | |
state, | |
value: translationX, | |
velocity: velocityX, | |
snapPoints: [0, 250], | |
offset, | |
config: SPRING_CONFIG, | |
}) | |
const clock = new Clock() | |
useCode( | |
() => | |
block([ | |
cond(openDrawerAnimatedState, [ | |
set( | |
offset, | |
spring({ | |
clock, | |
to: 250, | |
config: SPRING_CONFIG, | |
}), | |
), | |
cond(not(clockRunning(clock)), set(openDrawerAnimatedState, 0)), | |
]), | |
cond(closeDrawerAnimatedState, [ | |
set( | |
offset, | |
spring({ | |
clock, | |
to: 0, | |
config: SPRING_CONFIG, | |
}), | |
), | |
cond(not(clockRunning(clock)), [set(closeDrawerAnimatedState, 0)]), | |
]), | |
]), | |
[openDrawerAnimatedState, closeDrawerAnimatedState, offset, clock], | |
) | |
return ( | |
<View style={styles.container}> | |
<Backdrop translateX={translateX} onSetDrawerHidden={onSetDrawerHidden} /> | |
<BurgerMenu onSetDrawerActive={onSetDrawerActive} /> | |
<PanGestureHandler {...gestureHandler}> | |
<Animated.View> | |
<Drawer translateX={translateX} /> | |
</Animated.View> | |
</PanGestureHandler> | |
<View | |
style={{ | |
position: 'absolute', | |
left: 100, | |
top: 100, | |
backgroundColor: 'red', | |
padding: 10, | |
}}> | |
<ReText text={concat('', translateX)} style={{ color: 'white' }} /> | |
</View> | |
</View> | |
) | |
} | |
export default App | |
const styles = StyleSheet.create({ | |
drawer: { | |
width: 250, | |
height: wh, | |
backgroundColor: '#faf6f2', | |
position: 'absolute', | |
left: -250, | |
top: 0, | |
shadowColor: '#16485a', | |
shadowOffset: { width: 10, height: 7 }, | |
shadowRadius: 20, | |
shadowOpacity: 0.1, | |
}, | |
backdrop: { | |
...StyleSheet.absoluteFillObject, | |
backgroundColor: '#000', | |
}, | |
burgerButton: { | |
width: 44, | |
height: 44, | |
borderRadius: 22, | |
backgroundColor: '#fff', | |
shadowColor: '#000', | |
shadowOffset: { width: 2, height: 7 }, | |
shadowOpacity: 0.15, | |
position: 'absolute', | |
left: 16, | |
top: 100, | |
alignItems: 'center', | |
justifyContent: 'center', | |
}, | |
container: { | |
flex: 1, | |
backgroundColor: 'pink', | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment