Created
February 14, 2020 20:43
-
-
Save brentvatne/0ea48e9de9a256b8129349117a686e1b to your computer and use it in GitHub Desktop.
This file contains 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
import * as React from 'react'; | |
import { Text, View, StyleSheet } from 'react-native'; | |
import Constants from 'expo-constants'; | |
import { ShadowBox, NeomorphBox } from 'react-native-neomorph-shadows'; | |
import Animated, { Easing } from 'react-native-reanimated'; | |
import Svg, { | |
Defs, | |
LinearGradient, | |
Circle, | |
Stop | |
} from 'react-native-svg'; | |
const { | |
Value, | |
timing, | |
} = Animated; | |
const AnimatedCircle = Animated.createAnimatedComponent(Circle); | |
const RADIUS_CLOCK = 170; | |
const STROKE_WIDTH_SECOND_CIRCLE_VIEW = 20; | |
const RATIO_SVGTOVIEW = RADIUS_CLOCK / 50 | |
const RADIUS_SECOND_CIRCLE = (RADIUS_CLOCK - 10) / RATIO_SVGTOVIEW; | |
const STROKE_WIDTH_SECOND_CIRCLE = STROKE_WIDTH_SECOND_CIRCLE_VIEW / RATIO_SVGTOVIEW | |
const LENGTH_SECOND_CIRCLE = 2 * Math.PI * RADIUS_SECOND_CIRCLE; | |
const STEP_SECOND_LINE = LENGTH_SECOND_CIRCLE / 60; | |
const STEP_MINUTE_DEGREES = .1; | |
const STEP_HOUR_DEGREES = .00832; | |
export default class App extends React.PureComponent { | |
curDateTime = new Date(); | |
duration = this.curDateTime.getSeconds(); | |
state = { | |
hours: this.curDateTime.getHours(), | |
minute: this.curDateTime.getMinutes(), | |
seconds: this.curDateTime.getSeconds(), | |
rotationMinutes: STEP_MINUTE_DEGREES * ( this.curDateTime.getSeconds() + 60 * this.curDateTime.getMinutes() ), | |
rotationHours: STEP_HOUR_DEGREES * ( this.curDateTime.getSeconds() + 60 * this.curDateTime.getMinutes() + 3600 * this.curDateTime.getHours() ), | |
curLengthStrokeCircle: new Value(LENGTH_SECOND_CIRCLE), | |
tick: new Value(LENGTH_SECOND_CIRCLE - STEP_SECOND_LINE * this.curDateTime.getSeconds()) | |
} | |
animate(){ | |
timing(this.state.curLengthStrokeCircle, { | |
duration: 500, | |
toValue: this.state.tick, | |
easing: Easing.linear, | |
}).start(); | |
} | |
componentDidMount(){ | |
setInterval(() => { | |
const curDateTime = new Date(); | |
const seconds = curDateTime.getSeconds(); | |
const minutes = curDateTime.getMinutes(); | |
const hours = curDateTime.getHours(); | |
const rotationMinutes = STEP_MINUTE_DEGREES * ( seconds + 60 * minutes ); | |
const rotationHours = STEP_HOUR_DEGREES * ( seconds + 60 * minutes + 3600 * hours ); | |
this.setState({ | |
rotationMinutes, | |
rotationHours, | |
seconds, | |
minutes, | |
hours | |
}); | |
this.state.tick.setValue(LENGTH_SECOND_CIRCLE - STEP_SECOND_LINE * seconds); | |
if(seconds > 0) { | |
this.animate(); | |
} else { | |
this.state.curLengthStrokeCircle.setValue(LENGTH_SECOND_CIRCLE); | |
} | |
}, 1000) | |
} | |
render() { | |
const { | |
curLengthStrokeCircle, | |
rotationMinutes, | |
rotationHours, | |
hours, | |
minutes, | |
seconds | |
} = this.state; | |
return ( | |
<View style={styles.container}> | |
<Text style={styles.title}>Clock</Text> | |
<View style={styles.containerClock}> | |
<NeomorphBox inner style={styles.neomorph}> | |
<NeomorphBox style={styles.neomorph2}> | |
<NeomorphBox style={styles.neomorph3}> | |
<NeomorphBox style={styles.neomorphDotCenter}/> | |
</NeomorphBox> | |
</NeomorphBox> | |
</NeomorphBox> | |
<Svg height="100%" width="100%" viewBox="-50 -50 100 100" style={{position: 'absolute'}}> | |
<Defs> | |
<LinearGradient rotation="90" id="gradTime" x1="80%" y1="10%" x2="20%" y2="90%"> | |
<Stop offset="0%" stopColor="#FFE082" stopOpacity=".5"/> | |
<Stop offset="100%" stopColor="#D81B60" stopOpacity="1"/> | |
</LinearGradient> | |
</Defs> | |
<AnimatedCircle | |
r={RADIUS_SECOND_CIRCLE} | |
stroke="url(#gradTime)" | |
strokeWidth={STROKE_WIDTH_SECOND_CIRCLE} | |
fill="transparent" | |
strokeLinecap="round" | |
rotation="-90" | |
strokeDasharray={[LENGTH_SECOND_CIRCLE, LENGTH_SECOND_CIRCLE]} | |
strokeDashoffset={curLengthStrokeCircle} | |
/> | |
</Svg> | |
<View style={[styles.arrowHourContainer, {transform: [{rotate: rotationHours + 'deg'}]}]}> | |
<ShadowBox style={styles.arrowHour}/> | |
</View> | |
<View style={[styles.arrowMinuteContainer, {transform: [{rotate: rotationMinutes + 'deg'}]}]}> | |
<ShadowBox style={styles.arrowMinute}/> | |
</View> | |
</View> | |
<NeomorphBox style={styles.neomorphTimeContainer}> | |
<NeomorphBox inner style={styles.neomorphTimeContainer2}> | |
<Text style={styles.time}>{hours < 10 ? '0'+hours : hours} : {minutes < 10 ? '0' + minutes : minutes} : <Text style={{color: 'red'}}>{seconds < 10 ? '0' + seconds : seconds}</Text></Text> | |
</NeomorphBox> | |
</NeomorphBox> | |
</View> | |
); | |
} | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
alignItems: 'center', | |
justifyContent: 'space-between', | |
backgroundColor: '#ECF0F3', | |
paddingBottom: 100, | |
paddingTop: 80, | |
}, | |
title: { | |
fontSize: 36, | |
fontWeight: 'bold', | |
color: '#222', | |
}, | |
containerClock: { | |
width: RADIUS_CLOCK * 2, | |
height: RADIUS_CLOCK * 2, | |
}, | |
neomorph: { | |
shadowRadius: 1, | |
borderRadius: RADIUS_CLOCK * 2, | |
backgroundColor: '#ECF0F3', | |
width: RADIUS_CLOCK * 2, | |
height: RADIUS_CLOCK * 2, | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
neomorph2: { | |
shadowRadius: 1, | |
borderRadius: RADIUS_CLOCK - STROKE_WIDTH_SECOND_CIRCLE_VIEW, | |
backgroundColor: '#ECF0F3', | |
width: (RADIUS_CLOCK - STROKE_WIDTH_SECOND_CIRCLE_VIEW) * 2, | |
height: (RADIUS_CLOCK - STROKE_WIDTH_SECOND_CIRCLE_VIEW) * 2, | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
neomorph3: { | |
shadowRadius: 15, | |
borderRadius: RADIUS_CLOCK - 80, | |
backgroundColor: '#ECF0F3', | |
width: (RADIUS_CLOCK - 80) * 2, | |
height: (RADIUS_CLOCK - 80) * 2, | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
arrowMinuteContainer: { | |
position: 'absolute', | |
width: RADIUS_CLOCK * 2, | |
height: RADIUS_CLOCK * 2, | |
alignItems: 'center' | |
}, | |
arrowMinute: { | |
bottom: -50, | |
height: RADIUS_CLOCK - 30, | |
width: 2, | |
backgroundColor: 'red', | |
shadowRadius: 4, | |
shadowColor: 'red', | |
shadowOpacity: .3, | |
shadowOffset: {width: 1, height: 1} | |
}, | |
arrowHourContainer: { | |
transform: [{rotate: '45deg'}], | |
position: 'absolute', | |
width: RADIUS_CLOCK * 2, | |
height: RADIUS_CLOCK * 2, | |
alignItems: 'center' | |
}, | |
arrowHour: { | |
bottom: -80, | |
height: RADIUS_CLOCK - 60, | |
width: 2, | |
backgroundColor: 'black', | |
shadowRadius: 4, | |
shadowColor: 'black', | |
shadowOpacity: .3, | |
shadowOffset: {width: 1, height: 1} | |
}, | |
neomorphDotCenter: { | |
height: 12, | |
width: 12, | |
backgroundColor: 'black', | |
shadowRadius: 2, | |
borderRadius: 6 | |
}, | |
neomorphTimeContainer:{ | |
width: 240, | |
height: 80, | |
shadowRadius: 2, | |
borderRadius: 10, | |
backgroundColor: '#ECF0F3', | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
neomorphTimeContainer2:{ | |
width: 230, | |
height: 70, | |
shadowRadius: 2, | |
borderRadius: 5, | |
backgroundColor: '#ECF0F3', | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
time: { | |
fontSize: 42, | |
fontWeight: '100', | |
color: '#222', | |
//textAlign: 'center', | |
width: 190 | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment