当前位置:   article > 正文

vue3 + Element Plus自定义音频audio样式及控件_vue audio组件

vue audio组件

1、原生的audio控件写法及效果图:

在这里插入图片描述

由于audio标签原生样式不能修改UI样式,所以需要隐藏原生audio标签,重新写一个控件进行操作audio

2、自定义写法及效果图:

代码实现:

先封装一个组件audioPlayer.vue。注意:需提前安装了Element Plus

<template>
  <div>
    <audio
      @timeupdate="updateProgress"
      controls
      ref="audioRef"
      style="display: none"
    >
      <source :src="audioUrl" type="audio/mpeg" />
      您的浏览器不支持音频播放
    </audio>
    <div class="audio_right">
      <img
        v-if="!audioIsPlay"
        @click="playAudio"
        class="audio_icon"
        src="../../../assets/img/play.png"
        alt="播放"
      />
      <img
        v-if="audioIsPlay"
        @click="playAudio"
        class="audio_icon"
        src="../../../assets/img/pause.png"
        alt="暂停"
      />
      <el-slider
        class="slider_box"
        v-model="currentProgress"
        :show-tooltip="false"
        @input="handleProgressChange"
      />
      <div class="audio_time">
        <span class="audio_current">{{ audioStart }}</span>
        &nbsp;/&nbsp;
        <span class="audio_total">{{ durationTime }}</span>
      </div>
      <div class="volume">
        <div class="volume_progress" v-show="audioHuds">
          <el-slider
            vertical
            height="100px"
            class="volume_bar"
            v-model="audioVolume"
            :show-tooltip="false"
            @change="handleAudioVolume"
          />
        </div>
        <img
          class="volume_icon"
          v-if="audioVolume <= 0"
          @click.stop="audioHuds = !audioHuds"
          src="../../../assets/img/audio_mute.png"
          alt=""
        />
        <img
          class="volume_icon"
          v-if="audioVolume > 0"
          @click.stop="audioHuds = !audioHuds"
          src="../../../assets/img/audio_high.png"
          alt=""
        />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from "vue";
const props = defineProps({
  audioUrl: String,        //试听的链接
  isPauseTtsAudio: Boolean     //是否暂停播放试听
});
const audioIsPlay = ref(true); //音频是否在播放
const audioStart = ref("0:00");
const durationTime = ref("0:00"); //音频的总时长,显示的时间格式
const duration = ref(0); //音频的总时长
const audioVolume = ref(80); //音量的默认值是0.8
const audioHuds = ref(false); //是否显示音量slider
const audioRef = ref(null);
const currentProgress = ref(0);


watch(() => props.isPauseTtsAudio, (newVal, oldVal) => {
  if (newVal) {
    // 如果 isPauseTtsAudio 为 true,试听暂停
    handleCloseMusic();
  }
});
function handleCloseMusic() {
  audioRef.value.pause();
  audioIsPlay.value = true;
}
onMounted(() => {
  calculateDuration();
});
// 获取音频时长
function calculateDuration() {
  var myVid = audioRef.value;
  myVid.loop = false;
  myVid.src = props.audioUrl;
  // 监听音频播放完毕
  myVid.addEventListener(
    "ended",
    function () {
      audioIsPlay.value = true;
      currentProgress.value = 0;
    },
    false
  );
  if (myVid != null) {
    myVid.oncanplay = function () {
      duration.value = myVid.duration; // 计算音频时长
      durationTime.value = transTime(myVid.duration); //换算成时间格式
    };
    myVid.volume = 0.8; // 设置默认音量50%
    // 进入页面默认开始播放
    audioRef.value.play();
    audioIsPlay.value = false;
  }
}
// 音频播放时间换算
function transTime(duration) {
  const minutes = Math.floor(duration / 60);
  const seconds = Math.floor(duration % 60);
  const formattedMinutes = String(minutes).padStart(2, "0"); //padStart(2,"0") 使用0填充使字符串长度达到2
  const formattedSeconds = String(seconds).padStart(2, "0");
  return `${formattedMinutes}:${formattedSeconds}`;
}
// 播放暂停控制
function playAudio() {
  if (audioRef.value.paused) {
    audioRef.value.play();
    audioIsPlay.value = false;
  } else {
    audioRef.value.pause();
    audioIsPlay.value = true;
  }
}
// 根据当前播放时间,实时更新进度条
function updateProgress(e) {
  var value = e.target.currentTime / e.target.duration;
  if (audioRef.value.play) {
    currentProgress.value = value * 100;
    audioStart.value = transTime(audioRef.value.currentTime);
  }
}
//调整播放进度
const handleProgressChange = (val) => {
  console.log(val);
  if (!val) {
    return;
  }
  let currentTime = duration.value * (val / 100);
  // 更新音频的当前播放时间
  audioRef.value.currentTime = currentTime;
};
//调整音量
const handleAudioVolume = (val) => {
  audioRef.value.volume = val / 100;
};
</script>

<style lang="scss" scoped>
.audio_right {
  width: 230px;
  height: 40px;
  display: flex;
  align-items: center;
  background: linear-gradient(to left, #2e7bff 0%, #8ee7ff 100%);
  border-radius: 4px;
  padding: 0 10px;
  box-sizing: border-box;
  position: relative;
  .slider_box {
    width: 160px;
    height: 4px;
    border-radius: 5px;
    background-color: #f1f1f1;
    flex: 1;
    margin: 0 8px 4px;
  }
  .audio_icon {
    width: 20px;
    height: 20px;
    margin-bottom: 4px;
    cursor: pointer;
  }
  .audio_time {
    color: #f1f1f1;
    overflow: hidden;
    font-size: 12px;
    position: absolute;
    bottom: 3px;
    left: 80px;
    .audio_total {
      float: right;
    }
    .audio_current {
      float: left;
    }
  }
}
.volume {
  position: relative;
  .volume_progress {
    width: 32px;
    height: 140px;
    position: absolute;
    top: -142px;
    right: -4px;
  }
  .volume_bar {
    background: #fff;
    border-radius: 4px;
  }
  .volume_icon {
    width: 24px;
    height: 24px;
    cursor: pointer;
  }
}
</style>
<style lang="scss">
.el-slider__button-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}
.slider_box,
.volume_bar {
  .el-slider__button {
    width: 8px;
    height: 8px;
    border: none;
  }
  .el-slider__bar {
    background: #00db15;
  }
}
.slider_box {
  .el-slider__button-wrapper {
    width: 8px;
  }
}
.volume_bar {
  .el-slider__runway {
    margin: 0 14px !important;
  }
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252

父组件内引用自定义组件audioPlayer.vue

<template>
  <AudioPlayer :audioUrl="ttsAudioUrl" :isPauseTtsAudio="isPauseTtsAudio"></AudioPlayer>
</template>
<script setup>
import AudioPlayer from "../components/audioPlayer.vue";
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果图:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/961152
推荐阅读
相关标签
  

闽ICP备14008679号