Home > front end >  How to visualize sound waves like Google Meet does while a person talking in react native
How to visualize sound waves like Google Meet does while a person talking in react native

Time:08-25

I am trying to accomplish very similar animation in the below example.

Google Meet Voice Visualization 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:

enter image description here

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, enter image description here

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;

  • Related