效果图展示
插件安装
npm i wavesurfer
实现过程
<!--
@author: weileiming
@date: 2025-04-26 14:04:08
@description: 悬浮音波层
@props:isRecord: 录制状态waveOptions: 音波基础配置overlayStyle: 基础蒙层配置
@methods:togglePlay: 切换录制状态
-->
<template><div><!-- 悬浮音波层 --><div v-if="isRecord" class="floating-wave" :style="overlayStyle"><div id="waveform"></div></div></div></template><script setup>import { ref, nextTick, watch } from "vue";import WaveSurfer from "wavesurfer.js";import RecordPlugin from "wavesurfer.js/dist/plugins/record.esm.js";const props = defineProps({// 录制状态isRecord: {type: Boolean,required: true,},// 音波基础配置waveOptions: {type: Object,default: () => ({waveColor: "#4CAF50",progressColor: "#52C41A",height: 20,barWidth: 2,barGap: 3,barRadius: 2,barMinHeight: 1,normalize: true,interact: false,fillParent: true,pixelRatio: 1,minPxPerSec: 50,cursorWidth: 0,responsive: true,partialRender: true,removeMediaControl: true,hideScrollbar: true,}),},// 基础蒙层配置overlayStyle: {type: Object,default: () => ({background: 'rgba(0, 0, 0, 0.15)',width: '150px',height: '50px',minWidth: '150px',padding: '15px 10px',boxSizing:'border-box',}),},});const wavesurfer = ref(null);const recorder = ref(null);// 先声明 createWaveformconst createWaveform = async () => {await nextTick();try {wavesurfer.value = WaveSurfer.create({container: "#waveform",...props.waveOptions,});// 创建录音插件前先检查权限await navigator.mediaDevices.getUserMedia({ audio: true });recorder.value = wavesurfer.value.registerPlugin(RecordPlugin.create({scrollingWaveform: true,renderRecordedAudio: false,mediaRecorderOptions: {audioBitsPerSecond: 128000,},}));recorder.value.on("record-start", () => {console.log("录音开始");});recorder.value.on("record-end", () => {console.log("录音结束");});} catch (err) {console.error("创建 WaveSurfer 实例失败:", err);throw err;}};// 初始化录制const initRecorder = async () => {if (!wavesurfer.value) {await createWaveform();}};// 监听当前的启动状态 使用initRecorder 保证父组件获取到的状态和组件一致watch(() => props.isRecord,async (newVal) => {try {await initRecorder();if (newVal) {await recorder.value.startRecording();} else {await recorder.value.stopRecording();}} catch (error) {console.error("录音操作失败:", error);}},{ immediate: true });const togglePlay = async () => {try {await initRecorder();} catch (error) {console.error("麦克风访问错误:", error);alert("请允许访问麦克风");}};// 暴露方法defineExpose({togglePlay,});</script><style scoped></style>
使用示例
<script setup>
import { ref } from 'vue';
import SoundWave from './components/SoundWave/SoundWave.vue'
const mkRef = ref(null);
const isRecord = ref(false);
const handleToggle = () => {console.log('handleToggle', mkRef.value);mkRef.value.togglePlay();isRecord.value = !isRecord.value;
};
</script><template><button class="control-btn" @click="handleToggle">START</button><SoundWave ref="mkRef" :isRecord="isRecord"></SoundWave>
</template><style scoped>
.control-btn {background-color: #4CAF50; border: none; color: white; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px; cursor: pointer; border-radius: 4px; transition: background-color 0.3s ease;
}.control-btn:hover {background-color: #45a049;
}
</style>
npm下载该功能
上面功能可以直接去我的npm主页下载
npm i vue-sound-wave
说明
只针对麦克风音波效果开发,不做音频文件导出