Skip to content

Instantly share code, notes, and snippets.

@iremlopsum
Created April 21, 2020 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iremlopsum/ae062b37017e8c29ce5857886c9344e3 to your computer and use it in GitHub Desktop.
Save iremlopsum/ae062b37017e8c29ce5857886c9344e3 to your computer and use it in GitHub Desktop.
/* 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