Web Audio API 实践
这段代码直接引入即可,需要保证有 #app
元素存在且 /music.ogg
音频可以被获取到。
这段代码会在页面内生成一个 canvas
和 audio
元素。
点击了 audio
元素的播放按钮之后,就能够在一旁的 canvas
上看见音频可视化内容了。
const canvas = document.createElement('canvas')
const music = document.createElement('audio')
const app = document.querySelector('#app')
/**
* canvas 2d 上下文
*/
const ctx = canvas.getContext('2d')!
/**
* audio 上下文
*/
const audio = new AudioContext()
/**
* 音频源
*/
const source = audio.createMediaElementSource(music)
/**
* 分析器
*/
const analyser = audio.createAnalyser()
/**
* 音量设置
*/
const gain = audio.createGain()
/**
* 数据数组 数组大小为 analyser.frequencyBinCount
*/
const dataArray = new Uint8Array(analyser.frequencyBinCount)
/**
* 盒子大小
*/
const boxSize = 500
/**
* 原点半径
*/
const originRadius = 100
/**
* 原点 x 轴
*/
const originX = boxSize / 2
/**
* 原点 y 轴
*/
const originY = boxSize / 2
/**
* 原点线条最大长度
*/
const originLine = boxSize / 2
/**
* 圆弧角度
*/
const arg = Math.PI / 720
/**
* 源音频
*/
const sourceAudio = '/music.ogg'
canvas.height = boxSize
canvas.width = boxSize
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height) // 清除 canvas
// 移动到原点x轴 + 半径位置,原点y轴
// 直接移动到原点x轴,原点y轴,绘制圆时会从原点延伸一条线条到边框
ctx.moveTo(originX + originRadius, originY)
ctx.strokeStyle = 'pink' // 线条颜色为 粉色
// 绘制圆,并加粗
ctx.arc(originX, originY, originRadius - 2, 0, Math.PI * 2, true)
ctx.arc(originX, originY, originRadius - 1, 0, Math.PI * 2, true)
ctx.arc(originX, originY, originRadius, 0, Math.PI * 2, true)
ctx.stroke() // 绘制线条
analyser.getByteFrequencyData(dataArray) // 获取频谱数据
// 2304 是 64 和 36 的乘积
// 因为频谱数据长度为64位
for (let i = 0; i < 2304; i += 36) {
let len = originRadius + dataArray[i / 36] // 生成延伸线条长度
len = len > originLine ? originLine : len // 判断边界
ctx.beginPath()
// 生成随机颜色
ctx.strokeStyle = '#' + Math.random().toString(16).substring(2, 6)
// 绘制圆
ctx.arc(originX, originY, originRadius, arg * i, arg * i, false)
// 延伸线条
ctx.arc(originX, originY, len, arg * i, arg * i, false)
// 回退线条 若不如此 则会直接移动到原点绘制圆 导致从原点延伸线条
ctx.arc(originX, originY, originRadius, arg * (i + 1), arg * (i + 1), false)
// 延伸线条 加粗
ctx.arc(originX, originY, len, arg * (i + 1), arg * (i + 1), false)
// 回退线条
ctx.arc(originX, originY, originRadius, arg * (i - 1), arg * (i - 1), false)
// 延伸线条 加粗
ctx.arc(originX, originY, len, arg * (i - 1), arg * (i - 1), false)
ctx.stroke()
ctx.closePath()
}
requestAnimationFrame(draw)
}
music.controls = true
// music.src = '/music.ogg'
music.src = sourceAudio
music.onplay = () => {
analyser.fftSize = 128
gain.gain.value = 1
source.connect(gain)
gain.connect(analyser)
analyser.connect(audio.destination)
draw()
}
app?.append(canvas, music)
Web Audio API 实践
http://localhost:8080/archives/web-audio-api-shi-jian