v-audiopectrum 指令
介绍
v-audiopectrum
是一个音频频谱可视化指令,能够将音频元素的波形和频率数据实时渲染为动态图形。支持 三种内置可视化模式 和 完全自定义渲染,适用于音乐播放器、语音分析、音效可视化等场景。
核心特性
- 实时音频数据分析(时域/频域)
- 三种预制可视化模式:柱状图/波形图/圆形谱
- 响应式布局自动适配容器尺寸
- 自定义颜色方案和渲染逻辑
- 完善的资源清理机制
基础用法
请记得打开声音,没有声音是不会显示的哦!
音频统一为 《trun the lights back on》
查看代码
vue
<!-- AudioBasicDemo.vue -->
<template>
<div class="demo-container">
<audio
v-audiopectrum
controls
src="../.../../../../public/directives/audiopectrum/trun the lights back on.mp3"
></audio>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.demo-container {
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
margin: 20px 0;
}
</style>
进阶用法
圆形特效参数
查看代码
vue
<template>
<div class="demo-container">
<audio v-audiopectrum="options" controls :src="audioUrl"></audio>
<div class="controls">
<div class="control-group">
<label>显示模式:
<select v-model="options.mode">
<option value="bars">柱状图</option>
<option value="waveform">波形图</option>
<option value="circular">圆形模式</option>
</select>
</label>
</div>
<div class="control-group" v-if="options.mode === 'circular'">
<h4>圆形特效参数</h4>
<label>脉冲间隔:
<input type="range" v-model.number="options.circlePulseInterval" min="50" max="500">
{{ options.circlePulseInterval }}ms
</label>
<label>生命周期:
<input type="range" v-model.number="options.circleLifetime" min="500" max="2000">
{{ options.circleLifetime }}ms
</label>
<label>最大数量:
<input type="range" v-model.number="options.circleMaxCount" min="1" max="10">
{{ options.circleMaxCount }}
</label>
</div>
<div class="color-picker">
<label>起始颜色:
<input type="color" v-model="options.colors.start">
</label>
<label>结束颜色:
<input type="color" v-model="options.colors.end">
</label>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
const audioUrl = ref('../../../public/directives/audiopectrum/trun the lights back on.mp3')
const options = ref({
mode: 'circular',
fftSize: 1024,
colors: {
start: '#00ff88',
end: '#ff0077'
}
})
</script>
<style scoped>
.demo-container {
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
margin: 20px 0;
}
.controls {
margin-top: 15px;
padding: 15px;
background: #f8f8f8;
border-radius: 6px;
}
.control-group {
margin-bottom: 15px;
}
label {
display: block;
margin: 8px 0;
}
input[type="range"] {
vertical-align: middle;
}
.color-picker input[type="color"] {
width: 40px;
height: 30px;
margin-right: 10px;
}
</style>
自定义渲染指南
查看代码
vue
<template>
<div class="demo-container">
<audio
v-audiopectrum="{
mode: 'custom',
customDraw: particleDraw,
fftSize: 256
}"
controls
:src="audioUrl"
></audio>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const audioUrl = ref('../../../public/directives/audiopectrum/trun the lights back on.mp3')
// 自定义粒子绘制函数
const particleDraw = ({ ctx, dataArray, canvas, analyzer }) => {
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
ctx.fillRect(0, 0, canvas.width, canvas.height)
const centerX = canvas.width / 2
const centerY = canvas.height / 2
const maxDistance = Math.min(centerX, centerY) * 0.8
// 获取频率数据
const freqData = new Uint8Array(analyzer.frequencyBinCount)
analyzer.getByteFrequencyData(freqData)
// 绘制粒子
const particleCount = 200
for (let i = 0; i < particleCount; i++) {
const angle = (i / particleCount) * Math.PI * 2
const freqIndex = Math.floor((i / particleCount) * freqData.length)
const amplitude = freqData[freqIndex] / 255
// 计算位置
const distance = maxDistance * amplitude
const x = centerX + Math.cos(angle) * distance
const y = centerY + Math.sin(angle) * distance
// 绘制粒子
ctx.beginPath()
ctx.arc(x, y, 2 + amplitude * 4, 0, Math.PI * 2)
ctx.fillStyle = `hsla(${(freqIndex / freqData.length) * 360}, 70%, 50%, ${0.5 + amplitude * 0.5})`
ctx.fill()
}
// 绘制中心圆
ctx.beginPath()
ctx.arc(centerX, centerY, 10, 0, Math.PI * 2)
ctx.fillStyle = '#fff'
ctx.fill()
}
</script>
<style scoped>
.demo-container {
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
margin: 20px 0;
}
</style>
接口说明
通过 customDraw
参数传入自定义渲染函数,接收以下参数对象:
typescript
interface DrawContext {
ctx: CanvasRenderingContext2D // 画布绘制上下文
dataArray: Uint8Array // 当前帧音频数据(根据模式不同含义不同)
canvas: HTMLCanvasElement // 画布DOM元素
analyzer: AnalyserNode // Web Audio分析器实例
colors: {
// 颜色配置
start: string
end: string
}
}
API
属性名 | 说明 | 类型 | 是否必选 | 默认值 |
---|---|---|---|---|
mode | 可视化模式选择 | bars | waveform | circular | custom(自定义) | bars | |
fftSize | FFT转换窗口大小(需为2的幂次方) | number | 256 | |
colors | 渐变颜色配置(起始色/结束色) | { start: string, end: string } | { start: "#00ff00", end: "#ff0000" } | |
customDraw | 自定义渲染函数(需配合 mode: "custom" 使用) | function | null |
注意事项
WARNING
- 音频上下文限制
需要用户交互后初始化(点击事件后生效) 单页面最多同时存在 4个 实例
- 性能优化
移动端建议设置 fftSize: 128 复杂场景使用 requestIdleCallback 优化
- 内存管理
vue
<audio v-if="shouldShow" v-audiopectrum />
<!-- 正确 -->
<audio v-show="shouldShow" v-audiopectrum />
<!-- 错误 -->