Browse Source

添加语音动画效果

lex 1 year ago
parent
commit
cb06823f42

BIN
src/TUIKit/TUIComponents/assets/icon/voice-1.png


BIN
src/TUIKit/TUIComponents/assets/icon/voice-2.png


BIN
src/TUIKit/TUIComponents/assets/icon/voice-3.png


+ 30 - 23
src/TUIKit/TUIComponents/container/TUIChat/components/message-audio.vue

@@ -1,33 +1,27 @@
 <template>
-  <div
-    class="message-audio"
-    :class="[data.message.flow === 'out' && 'reserve']"
-    @click.stop="play"
-    :style="`width: ${data?.second * 10 + 40}Px`"
-  >
-    <i
-      class="icon icon-voice"
-      :class="[data.message.flow === 'out' && 'icon-reserve']"
-    ></i>
-    <label>{{ data.second }}s</label>
-    <audio ref="audio" :src="data.url"></audio>
+  <div class="message-audio" :class="[data.message.flow === 'out' && 'reserve']" @click.stop="play" :style="`width: ${data?.second * 10 + 40}Px`">
+    <i class="icon icon-voice" :class="[data.message.flow === 'out' && 'icon-reserve', data.message.isPlay ? 'icon-voice-active' : '']"></i>
+    <!-- 消息时间不到1s,默认显示1s -->
+    <label>{{ data.second ? data.second : 1 }}s</label>
+    <audio ref="audio" :src="data.url" @pause="onStopAnimation" @ended="onStopAnimation"></audio>
   </div>
 </template>
 
 <script lang="ts">
-import { defineComponent, watch, reactive, toRefs, ref } from 'vue';
+import { defineComponent, watch, reactive, toRefs, ref } from "vue";
 
 export default defineComponent({
   props: {
     data: {
       type: Object,
-      default: () => ({})
-    }
+      default: () => ({}),
+    },
   },
   setup(props: any, ctx: any) {
     const data = reactive({
-      data: {},
-      show: false
+      data: {} as any,
+      show: false,
+      isPlay: false, // 是否在播放
     });
 
     const audio = ref(null);
@@ -41,35 +35,48 @@ export default defineComponent({
     );
 
     const play = () => {
-      const audios = document.getElementsByTagName('audio');
+      const audios = document.getElementsByTagName("audio");
       for (const audio of audios) {
         if (!audio.paused) {
+          const parentNode: any = audio.parentNode;
+          parentNode.querySelector(".icon-voice").classList.remove("icon-voice-active");
           audio.pause();
           audio.load();
         }
       }
       const audioPlayer: any = audio.value;
+      const parentNode: any = audioPlayer.parentNode;
       if (audioPlayer.paused) {
         audioPlayer.play();
         data.show = true;
+        parentNode.querySelector(".icon-voice").classList.add("icon-voice-active");
       } else {
         audioPlayer.pause();
         audioPlayer.load();
         data.show = false;
+        parentNode.querySelector(".icon-voice").classList.remove("icon-voice-active");
+      }
+    };
+
+    const onStopAnimation = (e: any) => {
+      const parentNode = e.target.parentNode;
+      if (parentNode) {
+        parentNode.querySelector(".icon-voice").classList.remove("icon-voice-active");
       }
     };
 
     return {
       ...toRefs(data),
       audio,
-      play
+      play,
+      onStopAnimation,
     };
-  }
+  },
 });
 </script>
 <style lang="scss" scoped>
-@import url('../../../styles/common.scss');
-@import url('../../../styles/icon.scss');
+@import url("../../../styles/common.scss");
+@import url("../../../styles/icon.scss");
 .message-audio {
   display: flex;
   align-items: center;
@@ -78,7 +85,7 @@ export default defineComponent({
   max-width: 100%;
   overflow: hidden;
   .icon {
-    margin: 0 4Px;
+    margin: 0 4px;
   }
   audio {
     width: 0;

+ 23 - 0
src/TUIKit/TUIComponents/styles/icon.scss

@@ -149,6 +149,29 @@
   background-size: contain;
 }
 
+.icon-voice-active {
+  width: 16Px;
+  height: 16Px;
+  animation: voiceChange 1s ease-out infinite;
+}
+
+@keyframes voiceChange {
+  0% {
+    background: url('../assets/icon/voice-1.png') no-repeat;
+    background-size: contain;
+  }
+
+  50% {
+    background: url('../assets/icon/voice-2.png') no-repeat;
+    background-size: contain;
+  }
+
+  100% {
+    background: url('../assets/icon/voice-3.png') no-repeat;
+    background-size: contain;
+  }
+}
+
 .icon-reserve {
   transform: rotate(180deg);
 }

+ 2 - 2
src/main.ts

@@ -41,8 +41,8 @@ import { TUIComponents, TUICore, genTestUserSig } from "./TUIKit";
 console.log(import.meta.env.DEV, "import.meta.env.DEV");
 
 // 判断是否是测试环境的
-const SDKAppID = parseSearch.appId || hashSearch.appId || 1400799837; // import.meta.env.DEV ? 1400805079 : 1400799837; // 1400805079; // Your SDKAppID
-const secretKey = parseSearch.secretKey || hashSearch.secretKey || "37bfb220843e25e78768cadd0dc06756e460e55bd631354930a4149565a1d0c9"; //import.meta.env.DEV ? "c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30" : "37bfb220843e25e78768cadd0dc06756e460e55bd631354930a4149565a1d0c9"; //"c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30"; // Your secretKey
+const SDKAppID = parseSearch.appId || hashSearch.appId || 1400805079; // import.meta.env.DEV ? 1400805079 : 1400799837; // 1400805079; // Your SDKAppID
+const secretKey = parseSearch.secretKey || hashSearch.secretKey || "c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30"; //import.meta.env.DEV ? "c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30" : "37bfb220843e25e78768cadd0dc06756e460e55bd631354930a4149565a1d0c9"; //"c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30"; // Your secretKey
 const userID = parseSearch.userID; //|| "KT:140:TEACHER"; // User ID
 
 // init TUIKit