当一个人用 React Native 说话时,如何像 Google Meet 那样可视化声波

Alk*_*anV 2 javascript typescript react-native react-native-reanimated-v2

我试图在下面的示例中完成非常相似的动画。

Google Meet 语音可视化示例

borderWidth我的方法是这样的:获取语音音量数据,使用 shareValue将其附加到视图中react-native-reanimated。但是,由于borderWidth将自身附加到 的内部View,因此可视化效果如下例所示:

在此输入图像描述

下面你可以找到我的代码,

相关状态的初始化react-native-reanimated

  const voiceVolumeMeter = useSharedValue(0);
  const voiceVolumeMeterStyles = useAnimatedStyle(() => {
    return {
      borderWidth: voiceVolumeMeter.value,
    };
  });

Run Code Online (Sandbox Code Playgroud)

将体积数据附加到voiceVolumeMeter参数:

  voiceVolumeMeter.value = withSpring(55 + e.currentMetering!, {
    stiffness: 90,
    velocity: 12,
    mass: 0.5,
  });
Run Code Online (Sandbox Code Playgroud)

适用animatedStyleView

<Animated.View style={[styles.volumeMeterContainer, voiceVolumeMeterStyles]}>
  <View style={styles.recorderCircle}>
    <Text style={styles.audioRecorderTimer}>{recorderState.duration}</Text>
  </View>
</Animated.View>
Run Code Online (Sandbox Code Playgroud)

上面代码示例使用的样式:

  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,
  },
Run Code Online (Sandbox Code Playgroud)

这种方法基本上产生了与谷歌可视化完全相反的版本。我尝试过使用CSS的outline props,但不幸的是,react native不支持outline props。所以我需要另一种方法,但我在这里想不出一个绝妙的主意。

任何帮助将不胜感激,

此致。

Gau*_*Roy 5

嘿,谢谢你的问题,我这样做是为了复制见面聊天,

这是这里的实例,如有疑问,请放心,expo-snack-link

你的回答 先生在此输入图像描述

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;
Run Code Online (Sandbox Code Playgroud)