I am trying to accomplish very similar animation in the below example.
My approach was like this:
Get the voice volume data, append it to a view's borderWidth
using a sharedValue of react-native-reanimated
. However, since borderWidth
append itself to inside of the View
, the visualization is look like in the following example:
below you can find my code,
initialization of react-native-reanimated
related states.
const voiceVolumeMeter = useSharedValue(0);
const voiceVolumeMeterStyles = useAnimatedStyle(() => {
return {
borderWidth: voiceVolumeMeter.value,
};
});
appending volume data to the voiceVolumeMeter
parameter:
voiceVolumeMeter.value = withSpring(55 e.currentMetering!, {
stiffness: 90,
velocity: 12,
mass: 0.5,
});
applying animatedStyle
to View
<Animated.View style={[styles.volumeMeterContainer, voiceVolumeMeterStyles]}>
<View style={styles.recorderCircle}>
<Text style={styles.audioRecorderTimer}>{recorderState.duration}</Text>
</View>
</Animated.View>
styles that used above code example:
recorderCircle: {
width: 280,
height: 280,
borderRadius: 150,
borderColor: Colors.DUSTY_ORANGE,
justifyContent: 'center',
alignItems: 'center',
},
volumeMeterContainer: {
width: 290,
height: 290,
borderRadius: 140.5,
borderColor: Colors.WINDOWS_BLUE,
justifyContent: 'center',
padding: 20,
},
audioRecorderTimer: {
fontFamily: 'Quicksand',
fontStyle: 'normal',
fontWeight: '700',
fontSize: 45,
lineHeight: 56,
textAlign: 'center',
letterSpacing: -0.746023,
color: Colors.DUSTY_ORANGE,
},
This approach basically produced exactly reversed version of Google's visualization. I have tried with css's outline props but unfortunately, outline props are not supported on react native. so i need another approach but i could not come up with a brilliant idea here.
Any help will be appreciated,
Best regards.
CodePudding user response:
Hey thanks to your question i did this , to replicate meet chat,
This is the live example here, feel free for doubts,
import React, { PureComponent ,useEffect,useCallback , useState } from 'react';
import { StyleSheet, View, TouchableWithoutFeedback, Animated, Easing, Platform ,Text} from 'react-native';
const AppNew = (props={}) => {
const currentVolume = props?.currentVolume ?? 0
const maxVolume = 50;
const animationRef = React.useRef(new Animated.Value(0)).current
const startAnimations = useCallback(() => {
Animated.timing(animationRef,{
toValue:(currentVolume/maxVolume),
useNativeDriver:true,
duration:500
}).start()
},[animationRef,currentVolume])
useEffect(() => {
startAnimations()
},[startAnimations])
const polAnim = animationRef.interpolate({
inputRange:[0,1],
outputRange:[1,2],
extrapolate:'clamp'
})
return(
<Animated.View style={[styles.ripler,{
position:'absolute',
height:60,
width:60,
borderRadius:120,
transform:[{
scale:polAnim
}]
}]} >
</Animated.View>
)
}
const data = [1,6,39,40,50,22,7,15,12,1,6,39,40,50,22,7,15,18,1,6,39,40,50,22,7,15,12,1,6,39,40,50,22,7,15,12,1,6,39,40,50,22,7,15,12,1,6,39,40,50,22,7,15,12]
const App = () => {
const [currentTime, setTime ] = useState(0);
const [currIndex,setIndex] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
const newIndex = currIndex 1;
setTime(data[currIndex]);
setIndex(newIndex);
},500)
return () => clearInterval(interval)
},[currIndex])
return (
<View style={styles.pageContainer}>
<View style={{height:100,width:100}} >
<AppNew currentVolume={currentTime} />
<View style={{height:60,width:60,borderRadius:60,
alignItems:'center',
justifyContent:'center',
backgroundColor:'rgba(125,244,102,0.9)',
zIndex:3
}} >
<Text>Messi</Text>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
pageContainer: {
flex: 1,
alignItems:'center',
justifyContent:'center'
},
ripler:{
backgroundColor:'rgba(125,244,102,0.3)',
zIndex:2
},
contentContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
iconContainer: {
margin: 16,
alignItems: 'center',
justifyContent: 'center',
},
});
export default App;