So I made a component:
import React, { useState, useEffect } from 'react'; import { View, Animated, Easing, StyleSheet } from 'react-native'; const EnergyFlowAnimation = ({ duration = 1000, direction = 'left', style = null, value = 1, nrOfMarks = 5 }) => { const [arrowPosition] = useState(new Animated.Value(0)); const animation = Animated.timing(arrowPosition, { toValue: value, duration: duration, easing: Easing.linear, // easing: Easing.back(), useNativeDriver: true, }); const startAnimation = () => { animation.start(() => { animation.reset(); startAnimation(); }); }; useEffect(() => { startAnimation(); }, []); const Mark = () => { return ( <View style={{ width: 7, height: 5, backgroundColor: '#FF6B00', marginLeft: 3, borderRadius: 5 }} /> ); } let arrowTranslateX = 0; let arrowTranslateY = 0; let arrowRotation = '0deg'; switch (direction) { case 'left': arrowTranslateX = arrowPosition.interpolate({ inputRange: [0, 1], outputRange: [40, -10], }); arrowRotation = '180deg'; break; case 'right': arrowTranslateX = arrowPosition.interpolate({ inputRange: [0, 1], outputRange: [-10, 40], }); arrowRotation = '0deg'; break; case 'top': arrowTranslateY = arrowPosition.interpolate({ inputRange: [0, 1], outputRange: [40, -10], }); arrowRotation = '-90deg'; break; case 'down': arrowTranslateY = arrowPosition.interpolate({ inputRange: [0, 1], outputRange: [-10, 40], }); arrowRotation = '90deg'; break; default: arrowTranslateX = arrowPosition.interpolate({ inputRange: [0, 1], outputRange: [40, -10], }); } return ( <View> <Animated.View style={[ styles.roadLine, style, { transform: [{ translateX: arrowTranslateX }, { translateY: arrowTranslateY }, { rotate: arrowRotation }], // position: 'absolute', justifyContent: 'center', alignItems: 'center', alignSelf: 'center', }]}> {[...new Array(nrOfMarks)].map((_, index) => <View key={index}><Mark /></View>)} </Animated.View> </View> ); }; const styles = StyleSheet.create({ roadLine: { height: 10, flexDirection: 'row', }, }); export default EnergyFlowAnimation;
I call this component as follow:
<View style={[styles.bottom, { top: 20, flexDirection: 'row' }]} > <View style={{ backgroundColor: 'blue', width: 20, height: 20, zIndex: 1, right: -10 }} /> <EnergyFlowAnimation duration={500} direction='right' value={0.6} nrOfMarks={15} /> <View style={{ backgroundColor: 'yellow', width: 20, height: 20, right: 2 }} /> </View>
this gives me the following:
