Skip to content

Instantly share code, notes, and snippets.

@brentvatne
Created February 14, 2020 20:43
Show Gist options
  • Save brentvatne/0ea48e9de9a256b8129349117a686e1b to your computer and use it in GitHub Desktop.
Save brentvatne/0ea48e9de9a256b8129349117a686e1b to your computer and use it in GitHub Desktop.
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