使用Vue3+ts封装一个音频audio播放器
使用vue封装一个音频播放器
·
封装后音频播放器样式
大概思路是引入audio音频播放器标签,如果不设置control属性,音频标签就会隐藏,这样我们可以自己写音频播放器的样式,然后调用audio标签的方法,达到封装音频播放器的效果。
需要注意的是audio标签的canplay回调方法是音频加载完成之后调用,这时我们可以在这个回调方法里面获取音频的总长度。
代码如下
<template>
<div class="audio-player">
<img
src="@/assets/images/audio/play.png"
alt=""
class="play-icon"
@click="onPlay"
v-if="!playStatus"
/>
<img
src="@/assets/images/audio/pause.png"
alt=""
class="play-icon"
@click="onPause"
v-else
/>
<span class="play-time">
{{ transTime(audioCurrent) }}/{{ transTime(audioDuration) }}
</span>
<div class="play-progress">
<div
class="play-current-progress"
:style="{ width: `${playProgress}%` }"
></div>
</div>
<img
src="@/assets/images/audio/voice-open.png"
alt=""
class="play-voice"
v-if="audioVolume === 1"
@click="onSetVolume(0)"
/>
<img
src="@/assets/images/audio/voice-close.png"
alt=""
class="play-voice"
v-else
@click="onSetVolume(1)"
/>
<el-popover v-model:visible="speedVisible" placement="top" :width="50">
<div
v-for="item in speedList"
:key="item.value"
@click="onChangeSpeed(item.value)"
style="margin-bottom: 17px; cursor: pointer; text-align: center"
>
<span>{{ item.label }}</span>
</div>
<template #reference>
<span
class="play-speed"
@click="onHandleSpeed"
>{{ activeSpeed }}x</span>
</template>
</el-popover>
</div>
<audio ref="audioRef" :src="url" @canplay="onCanplay"></audio>
</template>
<script setup lang="ts">
import { ref, onBeforeMount } from "vue";
withDefaults(defineProps<{
url: string;
}>(),
{
url: "https://xxx.xxx.xx.xx/audio.mp3"
}
)
const speedList = [
{
label: "2x",
value: 2,
},
{
label: "1.5x",
value: 1.5,
},
{
label: "1x",
value: 1,
},
{
label: "0.75x",
value: 0.75,
},
];
onBeforeMount(() => {
clearInterval(timeInterval.value);
});
const speedVisible = ref<boolean>(false); // 设置音频播放速度弹窗
const audioRef = ref(); // 音频标签对象
const activeSpeed = ref(1); // 音频播放速度
const audioDuration = ref(0); // 音频总时长
const audioCurrent = ref(0); // 音频当前播放时间
const audioVolume = ref(1); // 音频声音,范围 0-1
const playStatus = ref<boolean>(false); // 音频播放状态:true 播放,false 暂停
const playProgress = ref(0); // 音频播放进度
const timeInterval = ref(); // 获取音频播放进度定时器
// 音频加载完毕的回调
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;
// 设置倍速
audioRef.value.playbackRate = value;
speedVisible.value = false;
};
const onHandleSpeed = () => {
speedVisible.value = !speedVisible.value;
};
// 设置声音
const onSetVolume = (value: number) => {
audioRef.value.volume = value;
audioVolume.value = value;
};
// 音频播放时间换算
const transTime = (value: number) => {
let time = "";
let h = parseInt(String(value / 3600));
value %= 3600;
let m = parseInt(String(value / 60));
let s = parseInt(String(value % 60));
if (h > 0) {
time = formatTime(h + ":" + m + ":" + s);
} else {
time = formatTime(m + ":" + s);
}
return time;
};
// 格式化时间显示,补零对齐
const formatTime = (value: string) => {
let time = "";
let s = value.split(":");
let i = 0;
for (; i < s.length - 1; i++) {
time += s[i].length == 1 ? "0" + s[i] : s[i];
time += ":";
}
time += s[i].length == 1 ? "0" + s[i] : s[i];
return time;
};
</script>
<style lang="less" scoped>
.audio-player {
width: 378px;
height: 52px;
background: linear-gradient(180deg, #505572 0%, #383b4f 100%);
border-radius: 8px;
padding: 9px 11px;
margin: 40px 26px 0;
box-sizing: border-box;
display: flex;
align-items: center;
.play-icon {
width: 34px;
height: 34px;
margin-right: 7px;
cursor: pointer;
}
.play-time {
width: 72px;
display: inline-block;
margin-right: 16px;
}
.play-progress {
width: 160px;
height: 4px;
background-color: #323547;
box-shadow: inset 0px 1px 0px 0px #20222d;
border-radius: 2px;
margin-right: 16px;
position: relative;
.play-current-progress {
height: 4px;
background: #00e5ff;
border-radius: 2px;
position: absolute;
top: 0;
left: 0;
}
}
.play-voice {
width: 20px;
height: 20px;
margin-right: 14px;
cursor: pointer;
}
.play-speed {
cursor: pointer;
color: #00e5ff;
}
}
</style>
更多推荐
已为社区贡献1条内容
所有评论(0)