Explorar o código

音频播放添加控制条

natasha hai 1 ano
pai
achega
81ccb5d7a2

+ 122 - 4
src/views/exercise_questions/create/components/common/AudioPlay.vue

@@ -1,6 +1,12 @@
 <template>
   <div class="audio-wrapper">
-    <span :class="[url ? 'audio-play' : 'audio-play not-url']" @click="playAudio">
+    <span
+      :class="[url ? 'audio-play' : 'audio-play not-url']"
+      :style="{
+        padding: showSlider ? '4px 16px' : '',
+      }"
+      @click="playAudio"
+    >
       <SvgIcon v-if="audio.paused" :size="audio.paused ? 20 : 14" :icon-class="iconClass" />
       <img
         v-else
@@ -11,13 +17,34 @@
         "
         class="voice-play"
       />
+
+      <template v-if="showSlider">
+        <span class="audio-time">{{ secondFormatConversion(audio.current_time) }}</span>
+        <el-slider
+          v-model="play_value"
+          class="audio-slider"
+          :format-tooltip="formatProcessToolTip"
+          @change="changeCurrentTime"
+        />
+        <span class="audio-time">{{ audio_allTime }}</span>
+      </template>
     </span>
-    <audio :id="fileId" :ref="fileId" :src="url" preload="metadata"></audio>
+
+    <audio
+      :id="fileId"
+      :ref="fileId"
+      :src="url"
+      preload="metadata"
+      @loadedmetadata="onLoadedmetadata"
+      @timeupdate="onTimeupdate"
+      @canplaythrough="oncanplaythrough"
+    ></audio>
   </div>
 </template>
 
 <script>
 import { GetFileURLMap } from '@/api/app';
+import { secondFormatConversion } from '@/utils/transform';
 
 export default {
   name: 'AudioPlay',
@@ -30,13 +57,28 @@ export default {
       type: String,
       default: '',
     },
+    showSlider: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {
+      secondFormatConversion,
       url: '',
       audio: {
         paused: true,
+        playing: false,
+        // 音频当前播放时长
+        current_time: 0,
+        // 音频最大播放时长
+        max_time: 0,
+        isPlaying: false,
+        loading: false,
       },
+      play_value: 0,
+      audio_allTime: null, // 展示总时间
+      aduio_currentTime: null, // 剩余时间
     };
   },
   computed: {
@@ -85,6 +127,50 @@ export default {
       }
       audio.paused ? audio.play() : audio.pause();
     },
+    // 进度条格式化toolTip
+    formatProcessToolTip(index) {
+      let indexs = parseInt((this.audio.max_time / 100) * index);
+      return secondFormatConversion(indexs);
+    },
+    // 点击 拖拽播放音频
+    changeCurrentTime(value) {
+      let audioId = this.fileId;
+      this.$refs[audioId].play();
+      this.audio.playing = true;
+      this.$refs[audioId].currentTime = parseInt((value / 100) * this.audio.max_time);
+    },
+    // 音频加载完之后
+    onLoadedmetadata(res) {
+      this.audio.max_time = parseInt(res.target.duration);
+      this.audio_allTime = secondFormatConversion(this.audio.max_time);
+    },
+    // 当音频当前时间改变后,进度条也要改变
+    onTimeupdate(res) {
+      let audioId = this.fileId;
+      this.audio.current_time = res.target.currentTime;
+      this.play_value = (this.audio.current_time / this.audio.max_time) * 100;
+      if (this.audio.current_time * 1000 > this.ed) {
+        this.$refs[audioId].pause();
+      }
+    },
+    onTimeupdateTime(res, playFlag) {
+      if (!res && res !== 0) return;
+      let audioId = this.audioId;
+      this.$refs[audioId].currentTime = res;
+      this.play_value = (res / this.audio.max_time) * 100;
+      if (playFlag) {
+        let audio = document.getElementsByTagName('audio');
+        audio.forEach((item) => {
+          if (item.id !== audioId) {
+            item.pause();
+          }
+        });
+        this.$refs[audioId].play();
+      }
+    },
+    oncanplaythrough() {
+      this.audio.loading = false;
+    },
   },
 };
 </script>
@@ -93,14 +179,15 @@ export default {
 .audio-wrapper {
   .audio-play {
     display: flex;
+    column-gap: 8px;
     align-items: center;
     justify-content: center;
-    width: 40px;
+    min-width: 40px;
     height: 40px;
     color: #fff;
     cursor: pointer;
     background-color: $main-color;
-    border-radius: 50%;
+    border-radius: 20px;
 
     &.not-url {
       color: #a1a1a1;
@@ -111,6 +198,37 @@ export default {
       width: 20px;
       height: 20px;
     }
+
+    .audio-time {
+      min-width: 35px;
+      font-size: 12px;
+      font-weight: 400;
+      line-height: 20px;
+    }
+
+    .audio-slider {
+      width: 82px;
+
+      :deep .el-slider__runway {
+        height: 4px;
+        background-color: #1853c6;
+      }
+
+      :deep .el-slider__button {
+        width: 4px;
+        height: 4px;
+        border: none;
+      }
+
+      :deep .el-slider__bar {
+        height: 4px;
+        background-color: #fff;
+      }
+
+      :deep .el-slider__button-wrapper {
+        top: -16px;
+      }
+    }
   }
 }
 </style>