mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-15 14:03:36 +08:00
feat: 添加音频可视化功能示例
This commit is contained in:
139
src/views/able/wavesurfer/index.vue
Normal file
139
src/views/able/wavesurfer/index.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<script setup lang="ts">
|
||||
import WaveSurfer from "wavesurfer.js";
|
||||
import { getTime } from "@pureadmin/utils";
|
||||
import { Play, Pause, Forward, Rewind } from "./svg";
|
||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||
|
||||
import "tippy.js/dist/tippy.css";
|
||||
import "tippy.js/animations/scale.css";
|
||||
import { directive as tippy } from "vue-tippy";
|
||||
|
||||
defineOptions({
|
||||
name: "Wavesurfer"
|
||||
});
|
||||
|
||||
const vTippy = tippy;
|
||||
const loading = ref(true);
|
||||
const wavesurfer = ref(null);
|
||||
const wavesurferRef = ref();
|
||||
// 音频总时长
|
||||
const totalTime = ref();
|
||||
// 音频当前播放位置时长
|
||||
const curTime = ref();
|
||||
// 音频是否正在播放
|
||||
const isPlay = ref(false);
|
||||
|
||||
function init() {
|
||||
wavesurfer.value = WaveSurfer.create({
|
||||
container: wavesurferRef.value,
|
||||
height: "auto",
|
||||
waveColor: "rgb(200, 0, 200)",
|
||||
progressColor: "rgb(100, 0, 100)",
|
||||
cursorColor: "rgb(64, 158, 255)",
|
||||
cursorWidth: 4,
|
||||
// backend: "MediaElement",
|
||||
url: "/audio/海阔天空.mp3"
|
||||
});
|
||||
|
||||
// 音频被解码后触发
|
||||
wavesurfer.value.on("decode", () => (loading.value = false));
|
||||
|
||||
// 当音频已解码并可以播放时触发
|
||||
wavesurfer.value.on("ready", () => {
|
||||
const { duration } = wavesurfer.value;
|
||||
const { m, s } = getTime(duration);
|
||||
totalTime.value = `${m}:${s}`;
|
||||
// 光标位置取中
|
||||
wavesurfer.value.setTime(duration / 2);
|
||||
// 设置音频音量(范围0-1)
|
||||
// wavesurfer.value.setVolume(1);
|
||||
});
|
||||
|
||||
// 音频位置改变时,播放期间连续触发
|
||||
wavesurfer.value.on("timeupdate", timer => {
|
||||
const { m, s } = getTime(timer);
|
||||
curTime.value = `${m}:${s}`;
|
||||
});
|
||||
|
||||
// 音频播放时触发
|
||||
wavesurfer.value.on("play", () => (isPlay.value = true));
|
||||
|
||||
// 音频暂停时触发
|
||||
wavesurfer.value.on("pause", () => (isPlay.value = false));
|
||||
}
|
||||
|
||||
onMounted(init);
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (wavesurfer.value) {
|
||||
wavesurfer.value.destroy();
|
||||
wavesurfer.value = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="font-medium">
|
||||
音频可视化,采用开源的
|
||||
<el-link
|
||||
href="https://wavesurfer-js.org/"
|
||||
target="_blank"
|
||||
style="margin: 0 4px 5px; font-size: 16px"
|
||||
>
|
||||
wavesurfer.js
|
||||
</el-link>
|
||||
<span class="text-[red]">
|
||||
(温馨提示:音频默认最大声音,播放时请调低电脑声音,以免影响到您)
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="loading"
|
||||
class="w-8/12 !m-auto !mt-[20px]"
|
||||
element-loading-background="transparent"
|
||||
>
|
||||
<div ref="wavesurferRef" />
|
||||
<div class="flex justify-between" v-show="totalTime">
|
||||
<span class="text-[#81888f]">00:00</span>
|
||||
<h1 class="text-4xl mt-2">{{ curTime }}</h1>
|
||||
<span class="text-[#81888f]">{{ totalTime }}</span>
|
||||
</div>
|
||||
<div class="flex mt-2 w-[180px] justify-around m-auto" v-show="totalTime">
|
||||
<Rewind
|
||||
class="cursor-pointer"
|
||||
v-tippy="{
|
||||
content: '快退(可长按)',
|
||||
placement: 'bottom',
|
||||
animation: 'scale'
|
||||
}"
|
||||
v-longpress:0:100="() => wavesurfer?.skip(-1)"
|
||||
/>
|
||||
<div
|
||||
class="cursor-pointer"
|
||||
v-tippy="{
|
||||
content: isPlay ? '暂停' : '播放',
|
||||
placement: 'bottom',
|
||||
animation: 'scale'
|
||||
}"
|
||||
@click="wavesurfer?.playPause()"
|
||||
>
|
||||
<Play v-if="isPlay" v-motion-pop />
|
||||
<Pause v-else v-motion-pop />
|
||||
</div>
|
||||
<Forward
|
||||
class="cursor-pointer"
|
||||
v-tippy="{
|
||||
content: '快进(可长按)',
|
||||
placement: 'bottom',
|
||||
animation: 'scale'
|
||||
}"
|
||||
v-longpress:0:100="() => wavesurfer?.skip(1)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
Reference in New Issue
Block a user