VUE3開箱即用的音頻播放組件完整代碼(基于原生audio)
1 效果展示



2 組件文件
AudioBase.vue
注:我是使用unocss語法來編寫css 如果項(xiàng)目沒有搭載unocss 將其相應(yīng)的轉(zhuǎn)換為css即可
<template>
<div
:style="{
height: `${100 + (textDiv ? textDiv.clientHeight + 10 : 0)}px`,
}"
p-10
bg-white
w-500
rounded-xl
border="1px solid gray-200 "
>
<div>
<div inline-flex text-size-6xl>
與
<div mx-5 inline-flex>{{ $props.customerName }}</div>
進(jìn)行通話
</div>
<div text-gray-500 inline-flex float-right>{{ $props.callTime }}</div>
</div>
<div class="bg-[--td-brand-color-1]" float-left flex-center pl-9 pr-11 rounded-55 w-330 h-40 mt-10>
<span w-50 inline-block mr-8> {{ transTime(audioCurrent) }} </span>
<div class="progress" w-120 mx-10 my-0>
<t-slider
v-model="playProgress"
:tooltip-props="{
theme: 'light',
content: transTime((changeVal * audioDuration) / 100),
}"
@change="change"
@change-end="changeEnd"
/>
</div>
<span w-50 inline-block mr-6>{{ transTime(audioDuration) }}</span>
<t-icon
v-if="!playStatus"
name="play-circle"
class="color-[--td-brand-color-6]"
w-34
h-34
ml-7
cursor-pointer
@click="onPlay"
></t-icon>
<t-icon
v-else
class="color-[--td-brand-color-6]"
w-34
h-34
ml-7
cursor-pointer
name="pause-circle"
@click="onPause"
></t-icon>
</div>
<audio ref="audioRef" :src="url" @canplay="onCanplay" />
<div ml-20 flex-center mt-10>
<t-popup v-model:visible="speedVisible" placement="top" :width="50">
<template #content>
<div
v-for="item in speedList"
:key="item.value"
mb-17
cursor-pointer
text-center
@click="onChangeSpeed(item.value)"
>
<span>{{ item.label }}</span>
</div>
</template>
<div inline ml-5 cursor-pointer>
<span class="text-[var(--td-brand-color-6)]" cursor-pointer @click="onHandleSpeed"
>{{ activeSpeed.toFixed(1) }}x</span
>
<div color-gray-6 text-12>倍速</div>
</div>
</t-popup>
<div inline ml-20 flex-col-center cursor-pointer>
<t-icon class="color-[var(--td-brand-color-6)]" ml-4 w-20 h-18 name="cloud-download"></t-icon>
<div color-gray-6 text-12>下載</div>
</div>
<div inline ml-20 flex-col-center cursor-pointer @click="handleText">
<t-icon class="color-[var(--td-brand-color-6)]" ml-5 w-20 h-18 name="translate"></t-icon>
<div color-gray-6 text-12>轉(zhuǎn)文字</div>
</div>
</div>
<div
v-if="showText"
ref="textDiv"
class="bg-[var(--td-brand-color-1)]"
p-10
rounded-5
mt-10
max-h-190
overflow-auto
overflow-y-auto
>
{{ $props.text }}
</div>
</div>
</template>
<script lang="ts" setup>
import moment from 'moment';
import { defineProps, onMounted, ref } from 'vue';
defineProps({
customerName: {
type: String,
default: 'xxx',// 名字
},
callTime: {
type: String,
default: '2024-08-02 16:20:35',
},
url: {
type: String,
default: 'http://music.163.com/song/media/outer/url?id=1337065812.mp3',
},
text: {
type: String,
default: '默認(rèn)的內(nèi)容還可以吧我是默認(rèn)的語音轉(zhuǎn)文字內(nèi)容看看長度如何呢默認(rèn)的內(nèi)容還可以吧我是默認(rèn)的語音轉(zhuǎn)文字',
},
});
const speedList = [
{
label: '2x',
value: 2,
},
{
label: '1.5x',
value: 1.5,
},
{
label: '1x',
value: 1,
},
{
label: '0.75x',
value: 0.75,
},
];
onMounted(() => {
clearInterval(timeInterval.value);
});
const speedVisible = ref<boolean>(false); // 設(shè)置音頻播放速度彈窗
const audioRef = ref(); // 音頻標(biāo)簽對(duì)象
const activeSpeed = ref(1); // 音頻播放速度
const audioDuration = ref(0); // 音頻總時(shí)長
const audioCurrent = ref(0); // 音頻當(dāng)前播放時(shí)間
const playStatus = ref<boolean>(false); // 音頻播放狀態(tài):true 播放,false 暫停
const playProgress = ref(0); // 音頻播放進(jìn)度
const timeInterval = ref(); // 獲取音頻播放進(jìn)度定時(shí)器
const showText = ref(false);
const textDiv = ref();
const changeVal = ref(0);
/** FUNCTION */
// 拖動(dòng)進(jìn)度條
const change = (val) => {
changeVal.value = val;
};
const changeEnd = (val: number) => {
if (audioDuration.value === 0) return;
playProgress.value = val;
audioRef.value.currentTime = (playProgress.value / 100) * audioDuration.value;
audioCurrent.value = audioRef.value.currentTime;
};
// 文字展示
const handleText = async () => {
showText.value = !showText.value;
};
// 音頻加載完畢的回調(diào)
const onCanplay = () => {
audioDuration.value = audioRef?.value.duration || 0;
};
const onPlay = async () => {
// 音頻播放完后,重新播放
if (playProgress.value === 100) audioRef.value.currentTime = 0;
await audioRef.value.play();
playStatus.value = true;
audioDuration.value = audioRef.value.duration;
timeInterval.value = setInterval(() => {
audioCurrent.value = audioRef.value.currentTime;
playProgress.value = (audioCurrent.value / audioDuration.value) * 100;
if (playProgress.value === 100) onPause();
}, 100);
};
const onPause = () => {
audioRef.value.pause();
playStatus.value = false;
clearInterval(timeInterval.value);
};
const onChangeSpeed = (value: number) => {
activeSpeed.value = value;
// 設(shè)置倍速
audioRef.value.playbackRate = value;
speedVisible.value = false;
};
const onHandleSpeed = () => {
speedVisible.value = !speedVisible.value;
};
// 音頻播放時(shí)間換算
const transTime = (value: number) => {
return `${Math.floor(value / 3600) > 9 ? Math.floor(value / 3600) : `0${Math.floor(value / 3600)}`}:${moment({
m: moment.duration(value, 'seconds').minutes(),
s: moment.duration(value, 'seconds').seconds(),
}).format('mm:ss')}`;
};
</script>
<style lang="less" scoped>
.progress {
::v-deep .sp-slider__button-wrapper {
width: 20px;
height: 20px;
margin-top: 8px;
}
::v-deep .sp-slider__button {
width: 12px;
height: 12px;
background-color: #4974f5;
}
}
</style>
3 使用嘗試
在外層父組件中使用如下:
先引入組件
<script setup lang="ts"> import AudioBase from '@/layouts/components/baseComponents/AudioBase.vue'; </script>
然后直接使用
<div bg-white p-10 rounded-5> 播放組件: <audio-base></audio-base> </div>
總結(jié)
到此這篇關(guān)于VUE3音頻播放組件的文章就介紹到這了,更多相關(guān)VUE3音頻播放組件(原生audio)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue左側(cè)菜單,樹形圖遞歸實(shí)現(xiàn)代碼
這篇文章主要介紹了vue左側(cè)菜單,樹形圖遞歸實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08
使用vue-cli3 創(chuàng)建vue項(xiàng)目并配置VS Code 自動(dòng)代碼格式化 vue語法高亮問題
這篇文章主要介紹了使用vue-cli3 創(chuàng)建vue項(xiàng)目,并配置VS Code 自動(dòng)代碼格式化 vue語法高亮問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
Vue實(shí)現(xiàn)渲染數(shù)據(jù)后控制滾動(dòng)條位置(推薦)
這篇文章主要介紹了Vue實(shí)現(xiàn)渲染數(shù)據(jù)后控制滾動(dòng)條位置,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
vue3移動(dòng)端嵌入pdf的多種方法小結(jié)
這篇文章主要介紹了vue3移動(dòng)端嵌入pdf的多種方法小結(jié),使用embed嵌入有好處也有缺點(diǎn),本文給大家講解的非常詳細(xì),需要的朋友可以參考下2023-10-10
vue項(xiàng)目引入本地bootstrap不生效問題及解決
這篇文章主要介紹了vue項(xiàng)目引入本地bootstrap不生效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
vue-cli創(chuàng)建項(xiàng)目ERROR?in?Conflict:?Multiple?assets?emit?dif
最近vue/cli創(chuàng)建項(xiàng)目后出現(xiàn)了錯(cuò)誤,下面這篇文章主要給大家介紹了關(guān)于vue-cli創(chuàng)建項(xiàng)目ERROR?in?Conflict:?Multiple?assets?emit?different?content?to?the?same?filename?index.html問題的解決辦法,需要的朋友可以參考下2023-02-02
詳解Vue如何實(shí)現(xiàn)自定義動(dòng)畫與動(dòng)畫效果設(shè)計(jì)
在Vue中,動(dòng)畫效果是非常有用的,它可以使用戶界面變得更加生動(dòng)、有趣,本文中我們將學(xué)習(xí)如何在Vue中進(jìn)行自定義動(dòng)畫與動(dòng)畫效果設(shè)計(jì),感興趣的可以了解一下2023-06-06

