This is a modified version of the Apple Watch like breathing animation from the video tutorial of Jimmy Cook. The animation goes full circle without going back and with easing in this one.
Demo Gif is after the gist code.
This is a modified version of the Apple Watch like breathing animation from the video tutorial of Jimmy Cook. The animation goes full circle without going back and with easing in this one.
Demo Gif is after the gist code.
/ ==================================================================== | |
// A MODIFIED VERSION OF THE APPLE WATCH LIKE BREATHING ANIMATION | |
// Cagil Seker [ÇAĞIL ŞEKER] (MadChuckle) - [email protected] | |
// ORIGINAL IDEA: Jimmy Cook (https://www.youtube.com/watch?v=dhF1kp0rGak) | |
// ==================================================================== | |
import React, {useRef} from 'react'; | |
import {Animated, Dimensions, Easing, StyleSheet, View} from 'react-native'; | |
const {width, height} = Dimensions.get('window'); | |
const circleSize = width / 2; | |
const App = () => { | |
const move = useRef(new Animated.Value(0)).current; | |
const breathIn = Easing.out(Easing.sin); | |
const breathOut = Easing.in(Easing.sin); | |
Animated.loop( | |
Animated.sequence([ | |
Animated.timing(move, { | |
toValue: 1, | |
duration: 5000, | |
easing: breathIn, | |
useNativeDriver: true, | |
}), | |
Animated.timing(move, { | |
toValue: 2, | |
duration: 3000, | |
easing: breathOut, | |
useNativeDriver: true, | |
}), | |
Animated.timing(move, { | |
toValue: 0.0, | |
duration: 0, | |
useNativeDriver: true, | |
}), | |
]), | |
).start(); | |
const translate = move.interpolate({ | |
inputRange: [0, 1, 2], | |
outputRange: [0, circleSize / 6, 0], | |
}); | |
return ( | |
<View style={styles.container}> | |
<View | |
style={{ | |
...StyleSheet.absoluteFill, | |
opacity: 0, | |
alignItems: 'center', | |
justifyContent: 'center', | |
}}> | |
<View | |
style={{ | |
backgroundColor: 'blue', | |
width: circleSize, | |
height: circleSize, | |
borderRadius: circleSize / 2, | |
}} | |
/> | |
</View> | |
{[0, 1, 2, 3, 4, 5, 6, 7].map((item) => { | |
const rotation = move.interpolate({ | |
inputRange: [0, 1, 2], | |
outputRange: [ | |
`${item * 45}deg`, // | |
`${item * 45 + 180}deg`, | |
`${item * 45 + 360}deg`, | |
], | |
}); | |
return ( | |
<View | |
key={item} | |
style={{ | |
...StyleSheet.absoluteFill, | |
alignItems: 'center', | |
justifyContent: 'center', | |
}}> | |
<Animated.View | |
style={{ | |
opacity: 0.15, | |
backgroundColor: '#d600d3', | |
width: circleSize, | |
height: circleSize, | |
borderRadius: circleSize / 2, | |
transform: [ | |
{ | |
rotateZ: rotation, | |
}, | |
{translateX: translate}, | |
{translateY: translate}, | |
], | |
}} | |
/> | |
</View> | |
); | |
})} | |
</View> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, // | |
backgroundColor: '#fff', | |
alignItems: 'center', | |
justifyContent: 'center', | |
}, | |
}); | |
export default App; |
This is great! Maybe if we add a breath-in/breath-out text in the middle or below to indicate the user how to breath would be a nice feature. Very neat!