First draft of timer element
This commit is contained in:
180
app/(tabs)/timer.tsx
Normal file
180
app/(tabs)/timer.tsx
Normal file
@@ -0,0 +1,180 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Animated,
|
||||
Dimensions,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
const colors = {
|
||||
black: '#323F4E',
|
||||
red: '#F76A6A',
|
||||
text: '#ffffff',
|
||||
};
|
||||
|
||||
const timers = [...Array(13).keys()].map((i) => (i === 0 ? 1 : i * 5));
|
||||
const ITEM_SIZE = width * 0.38;
|
||||
const ITEM_SPACING = (width - ITEM_SIZE) / 2;
|
||||
|
||||
/*
|
||||
Har bare skrevet timeren som en egen tab til å begynne med.
|
||||
Planen er at når bruker starter en task så vil de få opp denne timeren
|
||||
som viser TaskName og Description der tallene står nå
|
||||
Kanskje en animert figur hvis vi får tid
|
||||
*/
|
||||
export default function App() {
|
||||
const scrollX = React.useRef(new Animated.Value(0)).current;
|
||||
const [duration, setDuration] = React.useState(timers[0])
|
||||
const timerAnimation = React.useRef(new Animated.Value(height)).current
|
||||
const buttonAnimation = React.useRef(new Animated.Value(0)).current
|
||||
const animation = React.useCallback(() => {
|
||||
Animated.sequence([
|
||||
Animated.timing(buttonAnimation, {
|
||||
toValue: 1,
|
||||
duration: 300,
|
||||
useNativeDriver: true
|
||||
}),
|
||||
Animated.timing(timerAnimation, {
|
||||
toValue: 0,
|
||||
duration: 300,
|
||||
useNativeDriver: true
|
||||
}),
|
||||
Animated.timing(timerAnimation, {
|
||||
toValue: height,
|
||||
duration: duration * 1000,
|
||||
useNativeDriver: true
|
||||
}),
|
||||
]) .start(() => {
|
||||
Animated.timing(buttonAnimation, {
|
||||
toValue: 0,
|
||||
duration: 300,
|
||||
useNativeDriver: true
|
||||
}).start()
|
||||
})
|
||||
}, [duration])
|
||||
|
||||
const opacity = buttonAnimation.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [1, 0]
|
||||
})
|
||||
const translateY = buttonAnimation.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 200]
|
||||
})
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar hidden />
|
||||
<Animated.View
|
||||
style={[StyleSheet.absoluteFillObject, {
|
||||
height,
|
||||
width,
|
||||
backgroundColor: colors.red,
|
||||
transform: [{
|
||||
translateY: timerAnimation
|
||||
}]
|
||||
}]}
|
||||
/>
|
||||
<Animated.View
|
||||
style={[
|
||||
StyleSheet.absoluteFillObject,
|
||||
{
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
paddingBottom: 100,
|
||||
opacity,
|
||||
transform: [{
|
||||
translateY
|
||||
}]
|
||||
},
|
||||
]}>
|
||||
<TouchableOpacity
|
||||
onPress={animation}>
|
||||
<View
|
||||
style={styles.roundButton}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</Animated.View>
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: height / 3,
|
||||
left: 0,
|
||||
right: 0,
|
||||
flex: 1,
|
||||
}}>
|
||||
<Animated.FlatList
|
||||
data={timers}
|
||||
keyExtractor={item => item.toString()}
|
||||
horizontal
|
||||
bounces={false}
|
||||
onScroll={Animated.event(
|
||||
[{nativeEvent: {contentOffset: {x: scrollX}}}],
|
||||
{ useNativeDriver: true}
|
||||
)}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
onMomentumScrollEnd={ev => {
|
||||
const index = Math.round(ev.nativeEvent.contentOffset.x / ITEM_SIZE)
|
||||
setDuration(timers[index]);
|
||||
}}
|
||||
snapToInterval={ITEM_SIZE}
|
||||
decelerationRate={"fast"}
|
||||
style={{flexGrow: 0}}
|
||||
contentContainerStyle={{
|
||||
paddingHorizontal: ITEM_SPACING
|
||||
}}
|
||||
renderItem={({item, index}) => {
|
||||
const inputRange = [
|
||||
(index - 1) * ITEM_SIZE,
|
||||
index * ITEM_SIZE,
|
||||
(index + 1) * ITEM_SIZE,
|
||||
]
|
||||
|
||||
const opacity = scrollX.interpolate({
|
||||
inputRange,
|
||||
outputRange: [.4, 1, .4]
|
||||
})
|
||||
const scale = scrollX.interpolate({
|
||||
inputRange,
|
||||
outputRange: [.7, 1, .7]
|
||||
})
|
||||
return <View style={{width: ITEM_SIZE, justifyContent: 'center', alignItems: 'center'}}>
|
||||
<Animated.Text style={[styles.text, {
|
||||
opacity,
|
||||
transform: [{
|
||||
scale
|
||||
}]
|
||||
|
||||
}]}>
|
||||
{item}
|
||||
</Animated.Text>
|
||||
</View>
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.black,
|
||||
},
|
||||
roundButton: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 80,
|
||||
backgroundColor: colors.red,
|
||||
},
|
||||
text: {
|
||||
fontSize: ITEM_SIZE * 0.8,
|
||||
fontFamily: 'Menlo',
|
||||
color: colors.text,
|
||||
fontWeight: '900',
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user